Import Cobalt 2.9617 2016-08-17
diff --git a/src/README.md b/src/README.md
index 2d2efba..fb912c9 100644
--- a/src/README.md
+++ b/src/README.md
@@ -180,17 +180,25 @@
 
 Here's a quick and dirty guide to get to build the code on Linux.
 
-  1. Install the provided `depot_tools` archive into your favorite directory. It
-     has been slightly modified from Chromium's `depot_tools`.
+  1. Pull `depot_tools` into your favorite directory. It has been slightly
+     modified from Chromium's `depot_tools`.
+
+         git clone https://cobalt.googlesource.com/depot_tools
+
   2. Add that directory to the end of your `$PATH`.
-  3. Ensure you have these packages installed: `sudo apt-get install
-     libgles2-mesa-dev libpulse-dev libavformat-dev libavresample-dev
-     libasound2-dev libxrender-dev libxcomposite-dev`
+  3. Ensure you have these packages installed:
+
+         sudo apt-get install libgles2-mesa-dev libpulse-dev libavformat-dev \
+         libavresample-dev libasound2-dev libxrender-dev libxcomposite-dev
+
   4. Ensure you have the standard C++ header files installed
      (e.g. `libstdc++-4.8-dev`).
-  5. Remove bison-3 and install bison-2.7, or just make sure that bison-2.7 is
-     before bison-3 on your `$PATH`. (NOTE: We plan on moving to bison-3 in the
-     future.)
+  5. For now, we also require ruby:
+
+         sudo apt-get install ruby
+
+  6. Remove bison-3 and install bison-2.7. (NOTE: We plan on moving to bison-3
+     in the future.)
 
          $ sudo apt-get remove bison
          $ sudo apt-get install m4
@@ -203,27 +211,28 @@
          $ bison --version
          bison (GNU Bison) 2.7.12-4996
 
-  6. (From this directory) run GYP:
+  7. (From this directory) run GYP:
 
          cobalt/build/gyp_cobalt -C debug linux-x64x11
 
-  7. If you get a "clang not found" error, add the path to Cobalt's clang to
+  8. If you get a "clang not found" error, add the path to Cobalt's clang to
      your `$PATH` and rerun `gyp_cobalt` as above. For example:
      `/path/to/cobalt/src/third_party/llvm-build/Release+Asserts/bin`
-  8. Run Ninja:
+  9. Run Ninja:
 
          ninja -C out/linux-x64x11_debug cobalt
 
-  9. Run Cobalt:
+  10. Run Cobalt:
 
          out/linux-x64x11_debug/cobalt [--url=<url>]
 
       * If you want to use `http` instead of `https`, you must pass the
         `--allow_http` flag to the Cobalt command-line.
       * If you want to connect to an `https` host that doesn't have a
-        globally-validatable certificate, you must pass the
+        certificate validatable by our set of root CAs, you must pass the
         `--ignore_certificate_errors` flag to the Cobalt command-line.
-      * See `cobalt/browser/switches.cc` for more command-line options.
+      * See [`cobalt/browser/switches.cc`](cobalt/browser/switches.cc) for more
+        command-line options.
 
 
 ## Build Types
diff --git a/src/base/base.gyp b/src/base/base.gyp
index 3838ff6..bd8a374 100644
--- a/src/base/base.gyp
+++ b/src/base/base.gyp
@@ -1273,7 +1273,7 @@
           'variables': {
             'executable_name': 'base_unittests',
           },
-          'includes': [ '../cobalt/build/deploy.gypi' ],
+          'includes': [ '../starboard/build/deploy.gypi' ],
         },
       ],
     }],
diff --git a/src/base/base_paths_starboard.cc b/src/base/base_paths_starboard.cc
index 2b8a14a..fbad177 100644
--- a/src/base/base_paths_starboard.cc
+++ b/src/base/base_paths_starboard.cc
@@ -91,7 +91,7 @@
       return PathProviderStarboard(base::DIR_CACHE, result);
   }
 
-  NOTREACHED() << "key = " << key;
+  DLOG(ERROR) << "Could not resolve path for key = " << key;
   return false;
 }
 
diff --git a/src/base/circular_buffer_shell.cc b/src/base/circular_buffer_shell.cc
index a41d89a..ae58e4b 100644
--- a/src/base/circular_buffer_shell.cc
+++ b/src/base/circular_buffer_shell.cc
@@ -37,7 +37,8 @@
       length_(0),
       read_position_(0) {
   if (reserve_type == kReserve) {
-    IncreaseCapacityTo(max_capacity_);
+    base::AutoLock l(lock_);
+    IncreaseCapacityTo_Locked(max_capacity_);
   }
 }
 
@@ -65,7 +66,7 @@
   if (destination == NULL)
     length = 0;
 
-  ReadAndAdvanceUnchecked(destination, length, bytes_read);
+  ReadAndAdvanceUnchecked_Locked(destination, length, bytes_read);
 }
 
 void CircularBufferShell::Peek(void* destination,
@@ -77,12 +78,12 @@
   if (destination == NULL)
     length = 0;
 
-  ReadUnchecked(destination, length, source_offset, bytes_peeked);
+  ReadUnchecked_Locked(destination, length, source_offset, bytes_peeked);
 }
 
 void CircularBufferShell::Skip(size_t length, size_t* bytes_skipped) {
   base::AutoLock l(lock_);
-  ReadAndAdvanceUnchecked(NULL, length, bytes_skipped);
+  ReadAndAdvanceUnchecked_Locked(NULL, length, bytes_skipped);
 }
 
 bool CircularBufferShell::Write(const void* source,
@@ -93,7 +94,7 @@
   if (source == NULL)
     length = 0;
 
-  if (!EnsureCapacityToWrite(length)) {
+  if (!EnsureCapacityToWrite_Locked(length)) {
     return false;
   }
 
@@ -102,12 +103,13 @@
     size_t remaining = length - produced;
 
     // In this pass, write up to the contiguous space left.
-    size_t to_write = std::min(remaining, capacity_ - GetWritePosition());
+    size_t to_write =
+        std::min(remaining, capacity_ - GetWritePosition_Locked());
     if (to_write == 0)
       break;
 
     // Copy this segment and do the accounting.
-    void* destination = GetWritePointer();
+    void* destination = GetWritePointer_Locked();
     const void* src = add_to_pointer(source, produced);
     memcpy(destination, src, to_write);
     length_ += to_write;
@@ -124,12 +126,14 @@
   return length_;
 }
 
-void CircularBufferShell::ReadUnchecked(void* destination,
-                                        size_t destination_length,
-                                        size_t source_offset,
-                                        size_t* bytes_read) const {
+void CircularBufferShell::ReadUnchecked_Locked(void* destination,
+                                               size_t destination_length,
+                                               size_t source_offset,
+                                               size_t* bytes_read) const {
   DCHECK(destination != NULL || bytes_read != NULL);
 
+  lock_.AssertAcquired();
+
   size_t dummy = 0;
   if (!bytes_read) {
     bytes_read = &dummy;
@@ -168,9 +172,12 @@
   *bytes_read = consumed;
 }
 
-void CircularBufferShell::ReadAndAdvanceUnchecked(void* destination,
-                                                  size_t destination_length,
-                                                  size_t* bytes_read) {
+void CircularBufferShell::ReadAndAdvanceUnchecked_Locked(
+    void* destination,
+    size_t destination_length,
+    size_t* bytes_read) {
+  lock_.AssertAcquired();
+
   size_t dummy = 0;
   if (!bytes_read) {
     bytes_read = &dummy;
@@ -182,20 +189,26 @@
     return;
   }
 
-  ReadUnchecked(destination, destination_length, 0, bytes_read);
+  ReadUnchecked_Locked(destination, destination_length, 0, bytes_read);
   length_ -= *bytes_read;
   read_position_ = (read_position_ + *bytes_read) % capacity_;
 }
 
-void* CircularBufferShell::GetWritePointer() const {
-  return add_to_pointer(buffer_, GetWritePosition());
+void* CircularBufferShell::GetWritePointer_Locked() const {
+  lock_.AssertAcquired();
+
+  return add_to_pointer(buffer_, GetWritePosition_Locked());
 }
 
-size_t CircularBufferShell::GetWritePosition() const {
+size_t CircularBufferShell::GetWritePosition_Locked() const {
+  lock_.AssertAcquired();
+
   return (read_position_ + length_) % capacity_;
 }
 
-bool CircularBufferShell::EnsureCapacityToWrite(size_t length) {
+bool CircularBufferShell::EnsureCapacityToWrite_Locked(size_t length) {
+  lock_.AssertAcquired();
+
   if (capacity_ - length_ < length) {
     size_t capacity = std::max(2 * capacity_, length_ + length);
     if (capacity > max_capacity_)
@@ -206,13 +219,15 @@
       return false;
     }
 
-    return IncreaseCapacityTo(capacity);
+    return IncreaseCapacityTo_Locked(capacity);
   }
 
   return true;
 }
 
-bool CircularBufferShell::IncreaseCapacityTo(size_t capacity) {
+bool CircularBufferShell::IncreaseCapacityTo_Locked(size_t capacity) {
+  lock_.AssertAcquired();
+
   if (capacity <= capacity_) {
     return true;
   }
@@ -237,7 +252,7 @@
   size_t length = length_;
 
   // Copy the data over to the new buffer.
-  ReadUnchecked(buffer, length_, 0, NULL);
+  ReadUnchecked_Locked(buffer, length_, 0, NULL);
 
   // Adjust the accounting.
   length_ = length;
@@ -248,4 +263,19 @@
   return true;
 }
 
+size_t CircularBufferShell::GetMaxCapacity() const {
+  base::AutoLock l(lock_);
+
+  return max_capacity_;
+}
+
+void CircularBufferShell::IncreaseMaxCapacityTo(size_t new_max_capacity) {
+  base::AutoLock l(lock_);
+
+  DCHECK_GT(new_max_capacity, max_capacity_);
+  if (new_max_capacity > max_capacity_) {
+    max_capacity_ = new_max_capacity;
+  }
+}
+
 }  // namespace base
diff --git a/src/base/circular_buffer_shell.h b/src/base/circular_buffer_shell.h
index 4350af1..d7b364a 100644
--- a/src/base/circular_buffer_shell.h
+++ b/src/base/circular_buffer_shell.h
@@ -17,8 +17,8 @@
  public:
   enum ReserveType { kDoNotReserve, kReserve };
 
-  CircularBufferShell(size_t max_capacity,
-                      ReserveType reserve_type = kDoNotReserve);
+  explicit CircularBufferShell(size_t max_capacity,
+                               ReserveType reserve_type = kDoNotReserve);
   ~CircularBufferShell();
 
   // Clears out all data in the buffer, releasing any allocated memory.
@@ -53,16 +53,23 @@
   // Returns the length of the data left in the buffer to read.
   size_t GetLength() const;
 
+  // Returns the maximum capacity this circular buffer can grow to.
+  size_t GetMaxCapacity() const;
+
+  // Increase the max capacity to |new_max_capacity| which has to be greater
+  // than the previous one.  The content of the class will be kept.
+  void IncreaseMaxCapacityTo(size_t new_max_capacity);
+
  private:
   // Ensures that there is enough capacity to write length bytes to the
   // buffer. Returns false if it was unable to ensure that capacity due to an
   // allocation error, or if it would surpass the configured maximum capacity.
-  bool EnsureCapacityToWrite(size_t length);
+  bool EnsureCapacityToWrite_Locked(size_t length);
 
   // Increases the capacity to the given absolute size in bytes. Returns false
   // if there was an allocation error, or it would surpass the configured
   // maximum capacity.
-  bool IncreaseCapacityTo(size_t capacity);
+  bool IncreaseCapacityTo_Locked(size_t capacity);
 
   // Private workhorse for Read without the parameter validation or locking.
   // When |destination| is NULL, it purely calculates the the bytes that would
@@ -71,24 +78,24 @@
   // length.  It is caller's responsibility to adjust |read_position_| and
   // |length_| according to the return value, which is the actual number of
   // bytes read.
-  void ReadUnchecked(void* destination,
-                     size_t destination_length,
-                     size_t source_offset,
-                     size_t* bytes_read) const;
+  void ReadUnchecked_Locked(void* destination,
+                            size_t destination_length,
+                            size_t source_offset,
+                            size_t* bytes_read) const;
 
   // The same the as above functions except that it also advance the
   // |read_position_| and adjust the |length_| accordingly.
-  void ReadAndAdvanceUnchecked(void* destination,
-                               size_t destination_length,
-                               size_t* bytes_read);
+  void ReadAndAdvanceUnchecked_Locked(void* destination,
+                                      size_t destination_length,
+                                      size_t* bytes_read);
 
   // Gets a pointer to the current write position.
-  void* GetWritePointer() const;
+  void* GetWritePointer_Locked() const;
 
   // Gets the current write position.
-  size_t GetWritePosition() const;
+  size_t GetWritePosition_Locked() const;
 
-  const size_t max_capacity_;
+  size_t max_capacity_;
   void* buffer_;
   size_t capacity_;
   size_t length_;
diff --git a/src/base/circular_buffer_shell_unittest.cc b/src/base/circular_buffer_shell_unittest.cc
index 0d4aa1c..209ec74 100644
--- a/src/base/circular_buffer_shell_unittest.cc
+++ b/src/base/circular_buffer_shell_unittest.cc
@@ -452,3 +452,78 @@
     EXPECT_EQ(circular_buffer->GetLength(), 0);
   }
 }
+
+TEST(CircularBufferShellTest, IncreaseMaxCapacityTo) {
+  ClearPos();
+
+  scoped_ptr<base::CircularBufferShell> circular_buffer(
+      new base::CircularBufferShell(0));
+  EXPECT_EQ(circular_buffer->GetMaxCapacity(), 0);
+
+  // Increase max capacity by 20 to allow for expanding.
+  circular_buffer->IncreaseMaxCapacityTo(20);
+  EXPECT_EQ(circular_buffer->GetMaxCapacity(), 20);
+
+  // Set the size with the first write.
+  TestWrite(circular_buffer.get(), 10);
+
+  // Expand to the full capacity with the second write.
+  TestWrite(circular_buffer.get(), 10);
+
+  // Verify if the buffer is full by check the failure of writing one byte.
+  char ch = 'a';
+  size_t bytes_written = 0;
+  ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written));
+
+  // Increase max capacity to 30 to allow for further expanding.
+  circular_buffer->IncreaseMaxCapacityTo(30);
+  EXPECT_EQ(circular_buffer->GetMaxCapacity(), 30);
+
+  // Expand to capacity with the fourth write.
+  TestWrite(circular_buffer.get(), 10);
+
+  // Verify if the buffer is full by check the failure of writing one byte.
+  ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written));
+
+  // Drain the circular_buffer.
+  EXPECT_EQ(circular_buffer->GetLength(), 30);
+  TestRead(circular_buffer.get(), 30);
+  EXPECT_EQ(circular_buffer->GetLength(), 0);
+}
+
+TEST(CircularBufferShellTest, IncreaseMaxCapacityToWrapped) {
+  ClearPos();
+
+  scoped_ptr<base::CircularBufferShell> circular_buffer(
+      new base::CircularBufferShell(10));
+  EXPECT_EQ(circular_buffer->GetMaxCapacity(), 10);
+
+  // Expand to the full capacity with the first write.
+  TestWrite(circular_buffer.get(), 10);
+
+  // Partial read
+  TestRead(circular_buffer.get(), 5);
+
+  // The buffer is wrapped after the second write.
+  TestWrite(circular_buffer.get(), 5);
+
+  // Verify if the buffer is full by check the failure of writing one byte.
+  char ch = 'a';
+  size_t bytes_written = 0;
+  ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written));
+
+  // Increase max capacity to 20 to allow for further expanding.
+  circular_buffer->IncreaseMaxCapacityTo(20);
+  EXPECT_EQ(circular_buffer->GetMaxCapacity(), 20);
+
+  // Expand to capacity with the fourth write.
+  TestWrite(circular_buffer.get(), 10);
+
+  // Verify if the buffer is full by check the failure of writing one byte.
+  ASSERT_FALSE(circular_buffer->Write(&ch, 1, &bytes_written));
+
+  // Drain the circular_buffer.
+  EXPECT_EQ(circular_buffer->GetLength(), 20);
+  TestRead(circular_buffer.get(), 20);
+  EXPECT_EQ(circular_buffer->GetLength(), 0);
+}
diff --git a/src/cobalt/audio/audio.gyp b/src/cobalt/audio/audio.gyp
index 743b695..f13d2c3 100644
--- a/src/cobalt/audio/audio.gyp
+++ b/src/cobalt/audio/audio.gyp
@@ -73,7 +73,7 @@
       'variables': {
         'executable_name': 'audio_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/base/base.gyp b/src/cobalt/base/base.gyp
index c535446..6dc3864 100644
--- a/src/cobalt/base/base.gyp
+++ b/src/cobalt/base/base.gyp
@@ -76,7 +76,7 @@
         '<(DEPTH)/base/base.gyp:base',
       ],
       'conditions': [
-        ['OS != "starboard" or target_arch == "ps4"', {
+        ['OS != "starboard"', {
           'includes': [
             'copy_i18n_data.gypi',
           ],
@@ -107,7 +107,7 @@
       'variables': {
         'executable_name': 'base_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/bindings/code_generator_cobalt.py b/src/cobalt/bindings/code_generator_cobalt.py
index 7b6b66d..2aa694a 100644
--- a/src/cobalt/bindings/code_generator_cobalt.py
+++ b/src/cobalt/bindings/code_generator_cobalt.py
@@ -122,6 +122,12 @@
   return setter_operation
 
 
+def get_indexed_property_deleter(interface):
+  deleter_operation = get_indexed_special_operation(interface, 'deleter')
+  assert not deleter_operation or len(deleter_operation.arguments) == 1
+  return deleter_operation
+
+
 def get_named_special_operation(interface, special):
   special_operations = list(
       operation for operation in interface.operations
@@ -471,6 +477,8 @@
         interface, get_indexed_property_getter(interface))
     context['indexed_property_setter'] = contexts.special_method_context(
         interface, get_indexed_property_setter(interface))
+    context['indexed_property_deleter'] = contexts.special_method_context(
+        interface, get_indexed_property_deleter(interface))
     context['named_property_getter'] = contexts.special_method_context(
         interface, get_named_property_getter(interface))
     context['named_property_setter'] = contexts.special_method_context(
diff --git a/src/cobalt/bindings/contexts.py b/src/cobalt/bindings/contexts.py
index 0b91273..207d593 100644
--- a/src/cobalt/bindings/contexts.py
+++ b/src/cobalt/bindings/contexts.py
@@ -37,6 +37,7 @@
       'short': 'int16_t',
       'unsigned short': 'uint16_t',
       'long': 'int32_t',
+      'long long': 'int64_t',
       'unsigned long': 'uint32_t',
       'unsigned long long': 'uint64_t',
       'float': 'float',
@@ -211,28 +212,74 @@
   }
 
 
+def get_non_optional_arguments(arguments):
+  """Create non optional arguments list."""
+  return [argument for argument in arguments
+          if not argument['is_optional'] and not argument['is_variadic']]
+
+
+def get_optional_arguments(arguments):
+  """Create optional arguments list."""
+  return [argument for argument in arguments if argument['is_optional']]
+
+
+def get_num_default_arguments(optional_arguments):
+  """Return the number of default arguments."""
+  num_default_arguments = 0
+
+  for argument in optional_arguments:
+    if argument['default_value'] is not None:
+      num_default_arguments += 1
+
+  return num_default_arguments
+
+
+def get_variadic_argument(arguments):
+  """Return the variadic argument."""
+  length = len(arguments)
+
+  if length > 0 and arguments[length - 1]['is_variadic']:
+    return arguments[length - 1]
+  else:
+    return []
+
+
+def partial_context(interface, operation):
+  """Create partial template values for generating bindings."""
+  arguments = [argument_context(interface, a) for a in operation.arguments]
+  optional_arguments = get_optional_arguments(arguments)
+  num_default_arguments = get_num_default_arguments(optional_arguments)
+  return {
+      'arguments': arguments,
+      'non_optional_arguments': get_non_optional_arguments(arguments),
+      'optional_arguments': optional_arguments,
+      'num_default_arguments': num_default_arguments,
+      'variadic_argument': get_variadic_argument(arguments),
+      'has_non_default_optional_arguments': len(optional_arguments) >
+                                            num_default_arguments,
+  }
+
+
 def constructor_context(interface, constructor):
   """Create template values for generating constructor bindings."""
-  return {
-      'arguments':
-          [argument_context(interface, a) for a in constructor.arguments],
-      'call_with':
-          interface.extended_attributes.get('ConstructorCallWith', None),
-      'raises_exception':
-          (interface.extended_attributes.get('RaisesException', None)
-           == 'Constructor'),
+  context = {
+      'call_with': interface.extended_attributes.get('ConstructorCallWith',
+                                                     None),
+      'raises_exception': (interface.extended_attributes.get(
+          'RaisesException', None) == 'Constructor'),
   }
 
+  context.update(partial_context(interface, constructor))
+  return context
+
 
 def method_context(interface, operation):
   """Create template values for generating method bindings."""
-  return {
+  context = {
       'idl_name': operation.name,
       'name': capitalize_function_name(operation.name),
       'type': typed_object_to_cobalt_type(interface, operation),
       'is_static': operation.is_static,
-      'arguments':
-          [argument_context(interface, a) for a in operation.arguments],
       'call_with': operation.extended_attributes.get('CallWith', None),
       'raises_exception':
           operation.extended_attributes.has_key('RaisesException'),
@@ -240,6 +287,9 @@
       'unsupported': 'NotSupported' in operation.extended_attributes,
   }
 
+  context.update(partial_context(interface, operation))
+  return context
+
 
 def stringifier_context(interface):
   """Create template values for generating stringifier."""
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
index 38676ea..6db2e1d 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCDOMStringTestInterface.cc
@@ -107,6 +107,10 @@
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
     JSC::PropertyName property_name);
+JSC::JSValue getJSreadOnlyTokenProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
 JSC::JSValue getJSnullIsEmptyProperty(
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
@@ -451,6 +455,12 @@
         0,
         JSC::NoIntrinsic
     },
+    { "readOnlyTokenProperty",
+        JSC::DontDelete | JSC::ReadOnly,
+        reinterpret_cast<intptr_t>(getJSreadOnlyTokenProperty),
+        0,
+        JSC::NoIntrinsic
+    },
     { "nullIsEmptyProperty",
         JSC::DontDelete ,
         reinterpret_cast<intptr_t>(getJSnullIsEmptyProperty),
@@ -474,7 +484,7 @@
 
 // static
 const JSC::HashTable JSCDOMStringTestInterface::property_table_prototype = {
-    20,  // compactSize
+    21,  // compactSize
     15,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
@@ -744,6 +754,25 @@
   return result;
 }
 
+JSC::JSValue getJSreadOnlyTokenProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCDOMStringTestInterface", "get readOnlyTokenProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  DOMStringTestInterface* impl =
+      GetWrappableOrSetException<DOMStringTestInterface>(exec_state, slot_base);
+  if (!impl) {
+    return exec_state->exception();
+  }
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      impl->read_only_token_property());
+  return result;
+}
+
 JSC::JSValue getJSnullIsEmptyProperty(
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
index 810b872..5a523e7 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCDerivedInterface.cc
@@ -99,6 +99,7 @@
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
     JSC::PropertyName property_name);
+JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState*);
 JSC::EncodedJSValue functionJSderivedOperation(JSC::ExecState*);
 
 // These are declared unconditionally, but only defined if needed by the
@@ -181,13 +182,6 @@
     return JSC::CallTypeNone;
   }
 
-  // static override. This prevents this object from being called as a
-  // constructor, throwing a TypeError if the user attempts to do so.
-  //
-  // This method is defined when no constructors are defined on the IDL.
-  static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&) {
-    return JSC::ConstructTypeNone;
-  }
 
  private:
   typedef ConstructorBase BaseClass;
@@ -275,8 +269,7 @@
         &s_info);
 
     const int kNumArguments = 0;
-    // NativeExecutable must be non-null even if this is not actually callable.
-    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, NULL);
+    JSC::NativeExecutable* executable = global_data.getHostFunction(NULL, &constructorJSDerivedInterface);
 
     // Create the new interface object.
     InterfaceObject* new_interface_object =
@@ -632,6 +625,16 @@
   return result;
 }
 
+JSC::EncodedJSValue constructorJSDerivedInterface(JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+    scoped_refptr<DerivedInterface> new_object =
+        new DerivedInterface();
+    return JSC::JSValue::encode(ToJSValue(global_object, new_object));
+
+}
+
 JSC::EncodedJSValue functionJSderivedOperation(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCDerivedInterface", "call derivedOperation");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
index d7bb2ad..550c106 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCIndexedGetterInterface.cc
@@ -99,6 +99,7 @@
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
     JSC::PropertyName property_name);
+JSC::EncodedJSValue functionJSindexedDeleter(JSC::ExecState*);
 JSC::EncodedJSValue functionJSindexedGetter(JSC::ExecState*);
 JSC::EncodedJSValue functionJSindexedSetter(JSC::ExecState*);
 JSC::JSValue IndexedPropertyGetter(JSC::ExecState* exec_state,
@@ -332,6 +333,12 @@
 };
 
 const JSC::HashTableValue JSCIndexedGetterInterface::Prototype::property_table_values[] = {
+    { "indexedDeleter",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSindexedDeleter),
+        static_cast<intptr_t>(1),
+        JSC::NoIntrinsic
+    },
     { "indexedGetter",
         JSC::DontDelete | JSC::Function,
         reinterpret_cast<intptr_t>(functionJSindexedGetter),
@@ -355,8 +362,8 @@
 
 // static
 const JSC::HashTable JSCIndexedGetterInterface::Prototype::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
+    19,  // compactSize
+    15,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
 };  // JSCIndexedGetterInterface::Prototype::property_table_prototype
@@ -744,6 +751,40 @@
   return result;
 }
 
+JSC::EncodedJSValue functionJSindexedDeleter(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedDeleter");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  IndexedGetterInterface* impl =
+      GetWrappableOrSetException<IndexedGetterInterface>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  const size_t kMinArguments = 1;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<uint32_t >::ConversionType index;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &index);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  impl->IndexedDeleter(index);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
 JSC::EncodedJSValue functionJSindexedGetter(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCIndexedGetterInterface", "call indexedGetter");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
index d24db6a..e76d0d6 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCNumericTypesTestInterface.cc
@@ -143,6 +143,22 @@
     JSC::ExecState* exec,
     JSC::JSObject* this_object,
     JSC::JSValue value);
+JSC::JSValue getJSlongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
+void setJSlongLongProperty(
+    JSC::ExecState* exec,
+    JSC::JSObject* this_object,
+    JSC::JSValue value);
+JSC::JSValue getJSunsignedLongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
+void setJSunsignedLongLongProperty(
+    JSC::ExecState* exec,
+    JSC::JSObject* this_object,
+    JSC::JSValue value);
 JSC::JSValue getJSdoubleProperty(
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
@@ -164,6 +180,8 @@
 JSC::EncodedJSValue functionJSdoubleArgumentOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSdoubleReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSlongArgumentOperation(JSC::ExecState*);
+JSC::EncodedJSValue functionJSlongLongArgumentOperation(JSC::ExecState*);
+JSC::EncodedJSValue functionJSlongLongReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSlongReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSoctetArgumentOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSoctetReturnOperation(JSC::ExecState*);
@@ -172,6 +190,8 @@
 JSC::EncodedJSValue functionJSunrestrictedDoubleArgumentOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSunrestrictedDoubleReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSunsignedLongArgumentOperation(JSC::ExecState*);
+JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation(JSC::ExecState*);
+JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSunsignedLongReturnOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSunsignedShortArgumentOperation(JSC::ExecState*);
 JSC::EncodedJSValue functionJSunsignedShortReturnOperation(JSC::ExecState*);
@@ -432,6 +452,18 @@
         static_cast<intptr_t>(1),
         JSC::NoIntrinsic
     },
+    { "longLongArgumentOperation",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSlongLongArgumentOperation),
+        static_cast<intptr_t>(1),
+        JSC::NoIntrinsic
+    },
+    { "longLongReturnOperation",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSlongLongReturnOperation),
+        static_cast<intptr_t>(0),
+        JSC::NoIntrinsic
+    },
     { "longReturnOperation",
         JSC::DontDelete | JSC::Function,
         reinterpret_cast<intptr_t>(functionJSlongReturnOperation),
@@ -480,6 +512,18 @@
         static_cast<intptr_t>(1),
         JSC::NoIntrinsic
     },
+    { "unsignedLongLongArgumentOperation",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSunsignedLongLongArgumentOperation),
+        static_cast<intptr_t>(1),
+        JSC::NoIntrinsic
+    },
+    { "unsignedLongLongReturnOperation",
+        JSC::DontDelete | JSC::Function,
+        reinterpret_cast<intptr_t>(functionJSunsignedLongLongReturnOperation),
+        static_cast<intptr_t>(0),
+        JSC::NoIntrinsic
+    },
     { "unsignedLongReturnOperation",
         JSC::DontDelete | JSC::Function,
         reinterpret_cast<intptr_t>(functionJSunsignedLongReturnOperation),
@@ -509,7 +553,7 @@
 
 // static
 const JSC::HashTable JSCNumericTypesTestInterface::Prototype::property_table_prototype = {
-    80,  // compactSize
+    84,  // compactSize
     63,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
@@ -615,6 +659,18 @@
         reinterpret_cast<intptr_t>(setJSunsignedLongProperty),
         JSC::NoIntrinsic
     },
+    { "longLongProperty",
+        JSC::DontDelete ,
+        reinterpret_cast<intptr_t>(getJSlongLongProperty),
+        reinterpret_cast<intptr_t>(setJSlongLongProperty),
+        JSC::NoIntrinsic
+    },
+    { "unsignedLongLongProperty",
+        JSC::DontDelete ,
+        reinterpret_cast<intptr_t>(getJSunsignedLongLongProperty),
+        reinterpret_cast<intptr_t>(setJSunsignedLongLongProperty),
+        JSC::NoIntrinsic
+    },
     { "doubleProperty",
         JSC::DontDelete ,
         reinterpret_cast<intptr_t>(getJSdoubleProperty),
@@ -632,7 +688,7 @@
 
 // static
 const JSC::HashTable JSCNumericTypesTestInterface::property_table_prototype = {
-    39,  // compactSize
+    41,  // compactSize
     31,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
@@ -1113,6 +1169,98 @@
   }
 }
 
+JSC::JSValue getJSlongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "get longLongProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
+  if (!impl) {
+    return exec_state->exception();
+  }
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      impl->long_long_property());
+  return result;
+}
+
+void setJSlongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSObject* this_object,
+    JSC::JSValue value) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "set longLongProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return;
+  }
+  TypeTraits<int64_t >::ConversionType cobalt_value;
+  FromJSValue(exec_state, value,
+      kNoConversionFlags, &exception_state,
+      &cobalt_value);
+  if (exception_state.is_exception_set()) {
+    JSC::throwError(exec_state, exception_state.exception_object());
+    return;
+  }
+  // Check if argument conversion raised an exception.
+  if (!exec_state->hadException()) {
+    impl->set_long_long_property(cobalt_value);
+  }
+}
+
+JSC::JSValue getJSunsignedLongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "get unsignedLongLongProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, slot_base);
+  if (!impl) {
+    return exec_state->exception();
+  }
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      impl->unsigned_long_long_property());
+  return result;
+}
+
+void setJSunsignedLongLongProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSObject* this_object,
+    JSC::JSValue value) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "set unsignedLongLongProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return;
+  }
+  TypeTraits<uint64_t >::ConversionType cobalt_value;
+  FromJSValue(exec_state, value,
+      kNoConversionFlags, &exception_state,
+      &cobalt_value);
+  if (exception_state.is_exception_set()) {
+    JSC::throwError(exec_state, exception_state.exception_object());
+    return;
+  }
+  // Check if argument conversion raised an exception.
+  if (!exec_state->hadException()) {
+    impl->set_unsigned_long_long_property(cobalt_value);
+  }
+}
+
 JSC::JSValue getJSdoubleProperty(
     JSC::ExecState* exec_state,
     JSC::JSValue slot_base,
@@ -1345,6 +1493,59 @@
 
 }
 
+JSC::EncodedJSValue functionJSlongLongArgumentOperation(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongArgumentOperation");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  const size_t kMinArguments = 1;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<int64_t >::ConversionType arg1;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  impl->LongLongArgumentOperation(arg1);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
+JSC::EncodedJSValue functionJSlongLongReturnOperation(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "call longLongReturnOperation");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  TypeTraits<int64_t >::ReturnType return_value = impl->LongLongReturnOperation();
+  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
+
+}
+
 JSC::EncodedJSValue functionJSlongReturnOperation(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCNumericTypesTestInterface", "call longReturnOperation");
@@ -1557,6 +1758,59 @@
 
 }
 
+JSC::EncodedJSValue functionJSunsignedLongLongArgumentOperation(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongArgumentOperation");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  const size_t kMinArguments = 1;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<uint64_t >::ConversionType arg1;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  impl->UnsignedLongLongArgumentOperation(arg1);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
+JSC::EncodedJSValue functionJSunsignedLongLongReturnOperation(
+    JSC::ExecState* exec_state) {
+  TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongLongReturnOperation");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  JSC::JSObject* this_object =
+      exec_state->hostThisValue().toThisObject(exec_state);
+  NumericTypesTestInterface* impl =
+      GetWrappableOrSetException<NumericTypesTestInterface>(exec_state, this_object);
+  if (!impl) {
+    return JSC::JSValue::encode(exec_state->exception());
+  }
+
+  TypeTraits<uint64_t >::ReturnType return_value = impl->UnsignedLongLongReturnOperation();
+  return JSC::JSValue::encode(ToJSValue(global_object, return_value));
+
+}
+
 JSC::EncodedJSValue functionJSunsignedLongReturnOperation(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCNumericTypesTestInterface", "call unsignedLongReturnOperation");
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
index c451bd3..2f95415 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCOperationsTestInterface.cc
@@ -121,6 +121,8 @@
 JSC::EncodedJSValue functionJSvoidFunctionObjectArg(JSC::ExecState*);
 JSC::EncodedJSValue functionJSvoidFunctionStringArg(JSC::ExecState*);
 JSC::EncodedJSValue staticFunctionJSoverloadedFunction(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSoverloadedFunction1(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSoverloadedFunction2(JSC::ExecState*);
 
 // These are declared unconditionally, but only defined if needed by the
 // interface.
@@ -1510,6 +1512,33 @@
 JSC::EncodedJSValue staticFunctionJSoverloadedFunction(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCOperationsTestInterface", "call overloadedFunction");
+  const size_t num_arguments = exec_state->argumentCount();
+  switch(num_arguments) {
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticFunctionJSoverloadedFunction1(exec_state);
+      }
+      break;
+    }
+    case(2): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticFunctionJSoverloadedFunction2(exec_state);
+      }
+      break;
+    }
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  return JSC::throwVMTypeError(exec_state);
+}
+
+JSC::EncodedJSValue staticFunctionJSoverloadedFunction1(
+    JSC::ExecState* exec_state) {
   JSCGlobalObject* global_object =
       JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
   JSCExceptionState exception_state(global_object);
@@ -1533,6 +1562,42 @@
   return JSC::JSValue::encode(JSC::jsUndefined());
 
 }
+
+JSC::EncodedJSValue staticFunctionJSoverloadedFunction2(
+    JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+
+  const size_t kMinArguments = 2;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<double >::ConversionType arg1;
+  TypeTraits<double >::ConversionType arg2;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      (kConversionFlagRestricted),
+      &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+
+  DCHECK_LT(1, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(1),
+      (kConversionFlagRestricted),
+      &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  OperationsTestInterface::OverloadedFunction(arg1, arg2);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
 JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
     JSC::JSValue slot_base, JSC::PropertyName property_name) {
   NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
index d1870dd..dd16e18 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCPutForwardsInterface.cc
@@ -107,6 +107,14 @@
     JSC::ExecState* exec,
     JSC::JSObject* this_object,
     JSC::JSValue value);
+JSC::JSValue getJSstaticForwardingAttribute(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
+void setJSstaticForwardingAttribute(
+    JSC::ExecState* exec,
+    JSC::JSObject* this_object,
+    JSC::JSValue value);
 
 // These are declared unconditionally, but only defined if needed by the
 // interface.
@@ -218,6 +226,12 @@
 
 const JSC::HashTableValue JSCPutForwardsInterface::InterfaceObject::property_table_values[] = {
     // static functions will also go here.
+    { "staticForwardingAttribute",
+        JSC::DontDelete | JSC::ReadOnly,
+        reinterpret_cast<intptr_t>(getJSstaticForwardingAttribute),
+        0,
+        JSC::NoIntrinsic
+    },
     { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
 };  // JSCPutForwardsInterface::InterfaceObject::property_table_values
 
@@ -225,8 +239,8 @@
 const JSC::HashTable
 JSCPutForwardsInterface::InterfaceObject::property_table_prototype = {
     // Sizes will be calculated based on the number of static functions as well.
-    2,  // compactSize
-    1,  // compactSizeMask
+    4,  // compactSize
+    3,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
 };  // JSCPutForwardsInterface::InterfaceObject::property_table_prototype
@@ -684,6 +698,50 @@
   }
 
 }
+
+JSC::JSValue getJSstaticForwardingAttribute(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCPutForwardsInterface", "get staticForwardingAttribute");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      PutForwardsInterface::static_forwarding_attribute());
+  return result;
+}
+
+void setJSstaticForwardingAttribute(
+    JSC::ExecState* exec_state,
+    JSC::JSObject* this_object,
+    JSC::JSValue value) {
+  TRACE_EVENT0("JSCPutForwardsInterface", "set staticForwardingAttribute");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  {
+    scoped_refptr<ArbitraryInterface> forwarded_impl =
+        PutForwardsInterface::static_forwarding_attribute();
+    if (!forwarded_impl) {
+      return;
+    }
+  TypeTraits<std::string >::ConversionType cobalt_value;
+  FromJSValue(exec_state, value,
+      kNoConversionFlags, &exception_state,
+      &cobalt_value);
+  if (exception_state.is_exception_set()) {
+    JSC::throwError(exec_state, exception_state.exception_object());
+    return;
+  }
+  // Check if argument conversion raised an exception.
+  if (!exec_state->hadException()) {
+    forwarded_impl->set_arbitrary_property(cobalt_value);
+  }
+  }
+
+}
 JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
     JSC::JSValue slot_base, JSC::PropertyName property_name) {
   NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
index 965d7f0..4270480 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCStaticPropertiesInterface.cc
@@ -28,6 +28,8 @@
 #include "cobalt/script/global_object_proxy.h"
 #include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_object.h"
+#include "JSCArbitraryInterface.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "cobalt/script/javascriptcore/constructor_base.h"
 #include "cobalt/script/javascriptcore/conversion_helpers.h"
@@ -53,6 +55,8 @@
 namespace {
 using cobalt::bindings::testing::StaticPropertiesInterface;
 using cobalt::bindings::testing::JSCStaticPropertiesInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::JSCArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalObjectProxy;
 using cobalt::script::OpaqueHandle;
@@ -104,6 +108,11 @@
     JSC::JSObject* this_object,
     JSC::JSValue value);
 JSC::EncodedJSValue staticFunctionJSstaticFunction(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSstaticFunction1(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSstaticFunction2(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSstaticFunction3(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSstaticFunction4(JSC::ExecState*);
+JSC::EncodedJSValue staticFunctionJSstaticFunction5(JSC::ExecState*);
 
 // These are declared unconditionally, but only defined if needed by the
 // interface.
@@ -673,6 +682,52 @@
 JSC::EncodedJSValue staticFunctionJSstaticFunction(
     JSC::ExecState* exec_state) {
   TRACE_EVENT0("JSCStaticPropertiesInterface", "call staticFunction");
+  const size_t num_arguments = exec_state->argumentCount();
+  switch(num_arguments) {
+    case(0): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticFunctionJSstaticFunction1(exec_state);
+      }
+      break;
+    }
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JSC::JSValue arg = exec_state->argument(0);
+      if (arg.isNumber()) {
+        return staticFunctionJSstaticFunction2(exec_state);
+      }
+      if (true) {
+        return staticFunctionJSstaticFunction3(exec_state);
+      }
+      if (true) {
+        return staticFunctionJSstaticFunction2(exec_state);
+      }
+      break;
+    }
+    case(3): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JSC::JSValue arg = exec_state->argument(2);
+      if (arg.inherits(JSCArbitraryInterface::s_classinfo())) {
+        return staticFunctionJSstaticFunction5(exec_state);
+      }
+      if (true) {
+        return staticFunctionJSstaticFunction4(exec_state);
+      }
+      break;
+    }
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  return JSC::throwVMTypeError(exec_state);
+}
+
+JSC::EncodedJSValue staticFunctionJSstaticFunction1(
+    JSC::ExecState* exec_state) {
   JSCGlobalObject* global_object =
       JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
   JSCExceptionState exception_state(global_object);
@@ -681,6 +736,150 @@
   return JSC::JSValue::encode(JSC::jsUndefined());
 
 }
+
+JSC::EncodedJSValue staticFunctionJSstaticFunction2(
+    JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+
+  const size_t kMinArguments = 1;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  StaticPropertiesInterface::StaticFunction(arg);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
+JSC::EncodedJSValue staticFunctionJSstaticFunction3(
+    JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+
+  const size_t kMinArguments = 1;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<std::string >::ConversionType arg;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  StaticPropertiesInterface::StaticFunction(arg);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
+JSC::EncodedJSValue staticFunctionJSstaticFunction4(
+    JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+
+  const size_t kMinArguments = 3;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<int32_t >::ConversionType arg3;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+
+  DCHECK_LT(1, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(1),
+      kNoConversionFlags,
+      &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+
+  DCHECK_LT(2, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(2),
+      kNoConversionFlags,
+      &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
+
+JSC::EncodedJSValue staticFunctionJSstaticFunction5(
+    JSC::ExecState* exec_state) {
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+
+  const size_t kMinArguments = 3;
+  if (exec_state->argumentCount() < kMinArguments) {
+    return JSC::throwVMNotEnoughArgumentsError(exec_state);
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3;
+
+  DCHECK_LT(0, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(0),
+      kNoConversionFlags,
+      &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+
+  DCHECK_LT(1, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(1),
+      kNoConversionFlags,
+      &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+
+  DCHECK_LT(2, exec_state->argumentCount());
+  FromJSValue(exec_state,
+      exec_state->argument(2),
+      kNoConversionFlags,
+      &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return JSC::throwVMError(exec_state, exception_state.exception_object());
+  }
+  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
+  return JSC::JSValue::encode(JSC::jsUndefined());
+
+}
 JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
     JSC::JSValue slot_base, JSC::PropertyName property_name) {
   NOTREACHED();
diff --git a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
index fd026f2..2b7afe1 100644
--- a/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
+++ b/src/cobalt/bindings/generated/jsc/testing/JSCUnionTypesInterface.cc
@@ -29,7 +29,9 @@
 #include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_object.h"
 #include "JSCArbitraryInterface.h"
+#include "JSCBaseInterface.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
 
 #include "cobalt/script/javascriptcore/constructor_base.h"
 #include "cobalt/script/javascriptcore/conversion_helpers.h"
@@ -56,7 +58,9 @@
 using cobalt::bindings::testing::UnionTypesInterface;
 using cobalt::bindings::testing::JSCUnionTypesInterface;
 using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::BaseInterface;
 using cobalt::bindings::testing::JSCArbitraryInterface;
+using cobalt::bindings::testing::JSCBaseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalObjectProxy;
 using cobalt::script::OpaqueHandle;
@@ -123,6 +127,14 @@
     JSC::ExecState* exec,
     JSC::JSObject* this_object,
     JSC::JSValue value);
+JSC::JSValue getJSunionBaseProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name);
+void setJSunionBaseProperty(
+    JSC::ExecState* exec,
+    JSC::JSObject* this_object,
+    JSC::JSValue value);
 
 // These are declared unconditionally, but only defined if needed by the
 // interface.
@@ -449,13 +461,19 @@
         reinterpret_cast<intptr_t>(setJSnullableUnionProperty),
         JSC::NoIntrinsic
     },
+    { "unionBaseProperty",
+        JSC::DontDelete ,
+        reinterpret_cast<intptr_t>(getJSunionBaseProperty),
+        reinterpret_cast<intptr_t>(setJSunionBaseProperty),
+        JSC::NoIntrinsic
+    },
     { 0, 0, 0, 0, static_cast<JSC::Intrinsic>(0) }
 };  // JSCUnionTypesInterface::property_table_values
 
 // static
 const JSC::HashTable JSCUnionTypesInterface::property_table_prototype = {
-    10,  // compactSize
-    7,  // compactSizeMask
+    19,  // compactSize
+    15,  // compactSizeMask
     property_table_values,
     NULL  // table allocated at runtime
 };  // JSCUnionTypesInterface::property_table_prototype
@@ -796,6 +814,52 @@
     impl->set_nullable_union_property(cobalt_value);
   }
 }
+
+JSC::JSValue getJSunionBaseProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSValue slot_base,
+    JSC::PropertyName property_name) {
+  TRACE_EVENT0("JSCUnionTypesInterface", "get unionBaseProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  UnionTypesInterface* impl =
+      GetWrappableOrSetException<UnionTypesInterface>(exec_state, slot_base);
+  if (!impl) {
+    return exec_state->exception();
+  }
+
+  JSC::JSValue result = ToJSValue(
+      global_object,
+      impl->union_base_property());
+  return result;
+}
+
+void setJSunionBaseProperty(
+    JSC::ExecState* exec_state,
+    JSC::JSObject* this_object,
+    JSC::JSValue value) {
+  TRACE_EVENT0("JSCUnionTypesInterface", "set unionBaseProperty");
+  JSCGlobalObject* global_object =
+      JSC::jsCast<JSCGlobalObject*>(exec_state->lexicalGlobalObject());
+  JSCExceptionState exception_state(global_object);
+  UnionTypesInterface* impl =
+      GetWrappableOrSetException<UnionTypesInterface>(exec_state, this_object);
+  if (!impl) {
+    return;
+  }
+  TypeTraits<script::UnionType2<scoped_refptr<BaseInterface>, std::string > >::ConversionType cobalt_value;
+  FromJSValue(exec_state, value,
+      kNoConversionFlags, &exception_state,
+      &cobalt_value);
+  if (exception_state.is_exception_set()) {
+    JSC::throwError(exec_state, exception_state.exception_object());
+    return;
+  }
+  // Check if argument conversion raised an exception.
+  if (!exec_state->hadException()) {
+    impl->set_union_base_property(cobalt_value);
+  }
+}
 JSC::JSValue NamedPropertyGetter(JSC::ExecState* exec_state,
     JSC::JSValue slot_base, JSC::PropertyName property_name) {
   NOTREACHED();
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
index 3b1262d..d314658 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,128 @@
 
 namespace {
 
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->AnonymousIndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<uint32_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->AnonymousIndexedSetter(index, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsAnonymousIndexedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsAnonymousIndexedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsAnonymousIndexedGetterInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsAnonymousIndexedGetterInterfaceHandler::indexed_property_hooks = {
+  IsSupportedIndexProperty,
+  EnumerateSupportedIndexes,
+  GetIndexedProperty,
+  SetIndexedProperty,
+  NULL,
+};
+
+static base::LazyInstance<MozjsAnonymousIndexedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +242,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "AnonymousIndexedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +261,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  AnonymousIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<AnonymousIndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->length();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousIndexedGetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->length(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -162,6 +297,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -181,7 +320,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -201,8 +341,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "AnonymousIndexedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "AnonymousIndexedGetterInterface"));
+  const char name[] =
+      "AnonymousIndexedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -211,8 +352,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -244,7 +390,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsAnonymousIndexedGetterInterface::CreateInstance(
+JSObject* MozjsAnonymousIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -252,8 +398,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsAnonymousIndexedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
index 3a14754..56a2226 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousIndexedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsAnonymousIndexedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
index 7306f34..7cc34a6 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,128 @@
 
 namespace {
 
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->AnonymousNamedGetter(property_name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->AnonymousNamedSetter(property_name, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsAnonymousNamedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsAnonymousNamedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsAnonymousNamedGetterInterfaceHandler::named_property_hooks = {
+  IsSupportedNamedProperty,
+  EnumerateSupportedNames,
+  GetNamedProperty,
+  SetNamedProperty,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsAnonymousNamedGetterInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsAnonymousNamedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +242,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "AnonymousNamedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -137,6 +269,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -156,7 +292,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -176,8 +313,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "AnonymousNamedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "AnonymousNamedGetterInterface"));
+  const char name[] =
+      "AnonymousNamedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -186,8 +324,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -219,7 +362,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsAnonymousNamedGetterInterface::CreateInstance(
+JSObject* MozjsAnonymousNamedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -227,8 +370,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsAnonymousNamedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
index 3b0337b..36537ae 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsAnonymousNamedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
index 943b147..519c86f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,219 @@
 
 namespace {
 
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->AnonymousNamedGetter(property_name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->AnonymousNamedSetter(property_name, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->AnonymousIndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<uint32_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->AnonymousIndexedSetter(index, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsAnonymousNamedIndexedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsAnonymousNamedIndexedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsAnonymousNamedIndexedGetterInterfaceHandler::named_property_hooks = {
+  IsSupportedNamedProperty,
+  EnumerateSupportedNames,
+  GetNamedProperty,
+  SetNamedProperty,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsAnonymousNamedIndexedGetterInterfaceHandler::indexed_property_hooks = {
+  IsSupportedIndexProperty,
+  EnumerateSupportedIndexes,
+  GetIndexedProperty,
+  SetIndexedProperty,
+  NULL,
+};
+
+static base::LazyInstance<MozjsAnonymousNamedIndexedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +333,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "AnonymousNamedIndexedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +352,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  AnonymousNamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<AnonymousNamedIndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->length();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  AnonymousNamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<AnonymousNamedIndexedGetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->length(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -162,6 +388,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -181,7 +411,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -201,8 +432,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "AnonymousNamedIndexedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "AnonymousNamedIndexedGetterInterface"));
+  const char name[] =
+      "AnonymousNamedIndexedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -211,8 +443,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -244,7 +481,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateInstance(
+JSObject* MozjsAnonymousNamedIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -252,8 +489,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
index 0cb4295..6665fe1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsAnonymousNamedIndexedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsAnonymousNamedIndexedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
index 7625787..eb16ae9 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsArbitraryInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsArbitraryInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsArbitraryInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsArbitraryInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsArbitraryInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ArbitraryInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,18 +172,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ArbitraryInterface* impl =
-      WrapperPrivate::GetWrappable<ArbitraryInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->arbitrary_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ArbitraryInterface* impl =
+      wrapper_private->wrappable<ArbitraryInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->arbitrary_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_arbitraryProperty(
@@ -150,25 +194,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ArbitraryInterface* impl =
+      wrapper_private->wrappable<ArbitraryInterface>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ArbitraryInterface* impl =
-      WrapperPrivate::GetWrappable<ArbitraryInterface>(object);
+
   impl->set_arbitrary_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_arbitraryFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -181,17 +226,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   ArbitraryInterface* impl =
-      WrapperPrivate::GetWrappable<ArbitraryInterface>(object);
+      wrapper_private->wrappable<ArbitraryInterface>().get();
+
   impl->ArbitraryFunction();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -220,6 +265,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -239,7 +288,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -259,18 +309,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ArbitraryInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ArbitraryInterface"));
+  const char name[] =
+      "ArbitraryInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -302,7 +368,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsArbitraryInterface::CreateInstance(
+JSObject* MozjsArbitraryInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -310,8 +376,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsArbitraryInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -337,9 +414,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<ArbitraryInterface> new_object =
+      new ArbitraryInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
index ab9c011..1ca5d0d 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsArbitraryInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsArbitraryInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
index 99489af..1213bf6 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsBaseInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsBaseInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsBaseInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsBaseInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsBaseInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "BaseInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,25 +172,26 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  BaseInterface* impl =
-      WrapperPrivate::GetWrappable<BaseInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->base_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  BaseInterface* impl =
+      wrapper_private->wrappable<BaseInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->base_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_baseOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -162,17 +204,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   BaseInterface* impl =
-      WrapperPrivate::GetWrappable<BaseInterface>(object);
+      wrapper_private->wrappable<BaseInterface>().get();
+
   impl->BaseOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -201,6 +243,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -220,7 +266,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -240,18 +287,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "BaseInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "BaseInterface"));
+  const char name[] =
+      "BaseInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -283,7 +346,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsBaseInterface::CreateInstance(
+JSObject* MozjsBaseInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -291,8 +354,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsBaseInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -318,9 +392,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<BaseInterface> new_object =
+      new BaseInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
index d170a1f..6a9f2c0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBaseInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsBaseInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
index 9cd00aa..b334f88 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsBooleanTypeTestInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsBooleanTypeTestInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsBooleanTypeTestInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsBooleanTypeTestInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsBooleanTypeTestInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "BooleanTypeTestInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  BooleanTypeTestInterface* impl =
-      WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->boolean_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  BooleanTypeTestInterface* impl =
+      wrapper_private->wrappable<BooleanTypeTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->boolean_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_booleanProperty(
@@ -148,25 +192,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  BooleanTypeTestInterface* impl =
+      wrapper_private->wrappable<BooleanTypeTestInterface>().get();
   TypeTraits<bool >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  BooleanTypeTestInterface* impl =
-      WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object);
+
   impl->set_boolean_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_booleanArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -179,37 +224,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  BooleanTypeTestInterface* impl =
+      wrapper_private->wrappable<BooleanTypeTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<bool >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  BooleanTypeTestInterface* impl =
-      WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object);
+
   impl->BooleanArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_booleanReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -222,20 +271,23 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   BooleanTypeTestInterface* impl =
-      WrapperPrivate::GetWrappable<BooleanTypeTestInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->BooleanReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<BooleanTypeTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->BooleanReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -271,6 +323,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -290,7 +346,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -310,8 +367,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "BooleanTypeTestInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "BooleanTypeTestInterface"));
+  const char name[] =
+      "BooleanTypeTestInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -320,8 +378,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -353,7 +416,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsBooleanTypeTestInterface::CreateInstance(
+JSObject* MozjsBooleanTypeTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -361,8 +424,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsBooleanTypeTestInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
index 667bde9..d240a38 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsBooleanTypeTestInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsBooleanTypeTestInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
index c7865a2..a6360ce 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsCallbackFunctionInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsCallbackFunctionInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsCallbackFunctionInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsCallbackFunctionInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsCallbackFunctionInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "CallbackFunctionInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +174,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
-  TypeTraits<CallbackFunctionInterface::VoidFunction >::ReturnType value =
-      impl->callback_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->callback_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_callbackAttribute(
@@ -152,18 +196,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->set_callback_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableCallbackAttribute(
@@ -171,18 +218,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
-  TypeTraits<CallbackFunctionInterface::VoidFunction >::ReturnType value =
-      impl->nullable_callback_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_callback_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableCallbackAttribute(
@@ -190,25 +240,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->set_nullable_callback_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_takesFunctionThatReturnsString(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -221,37 +272,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackFunctionInterface::FunctionThatReturnsString >::ConversionType cb;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &cb);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &cb);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->TakesFunctionThatReturnsString(cb);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_takesFunctionWithNullableParameters(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -264,37 +319,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackFunctionInterface::FunctionWithNullableParameters >::ConversionType cb;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &cb);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &cb);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->TakesFunctionWithNullableParameters(cb);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_takesFunctionWithOneParameter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -307,37 +366,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackFunctionInterface::FunctionWithOneParameter >::ConversionType cb;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &cb);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &cb);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->TakesFunctionWithOneParameter(cb);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_takesFunctionWithSeveralParameters(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -350,37 +413,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackFunctionInterface::FunctionWithSeveralParameters >::ConversionType cb;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &cb);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &cb);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->TakesFunctionWithSeveralParameters(cb);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_takesVoidFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -393,30 +460,36 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackFunctionInterface* impl =
+      wrapper_private->wrappable<CallbackFunctionInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackFunctionInterface::VoidFunction >::ConversionType cb;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &cb);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &cb);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackFunctionInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackFunctionInterface>(object);
+
   impl->TakesVoidFunction(cb);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -479,6 +552,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -498,7 +575,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -518,8 +596,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "CallbackFunctionInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "CallbackFunctionInterface"));
+  const char name[] =
+      "CallbackFunctionInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -528,8 +607,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -561,7 +645,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsCallbackFunctionInterface::CreateInstance(
+JSObject* MozjsCallbackFunctionInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -569,8 +653,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsCallbackFunctionInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
index 31b6166..e85e0f2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackFunctionInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsCallbackFunctionInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
index a08045a..3a9b54c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/single_operation_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsCallbackInterfaceInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsCallbackInterfaceInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsCallbackInterfaceInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsCallbackInterfaceInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsCallbackInterfaceInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "CallbackInterfaceInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +174,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  CallbackInterfaceInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object);
-  TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ReturnType value =
-      impl->callback_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackInterfaceInterface* impl =
+      wrapper_private->wrappable<CallbackInterfaceInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->callback_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_callbackAttribute(
@@ -152,25 +196,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackInterfaceInterface* impl =
+      wrapper_private->wrappable<CallbackInterfaceInterface>().get();
   TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackInterfaceInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object);
+
   impl->set_callback_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_registerCallback(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -183,37 +228,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  CallbackInterfaceInterface* impl =
+      wrapper_private->wrappable<CallbackInterfaceInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<CallbackInterfaceTraits<SingleOperationInterface > >::ConversionType callback_interface;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &callback_interface);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &callback_interface);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  CallbackInterfaceInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object);
+
   impl->RegisterCallback(callback_interface);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_someOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -226,17 +275,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   CallbackInterfaceInterface* impl =
-      WrapperPrivate::GetWrappable<CallbackInterfaceInterface>(object);
+      wrapper_private->wrappable<CallbackInterfaceInterface>().get();
+
   impl->SomeOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -272,6 +321,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -291,7 +344,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -311,8 +365,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "CallbackInterfaceInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "CallbackInterfaceInterface"));
+  const char name[] =
+      "CallbackInterfaceInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -321,8 +376,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -354,7 +414,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsCallbackInterfaceInterface::CreateInstance(
+JSObject* MozjsCallbackInterfaceInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -362,8 +422,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsCallbackInterfaceInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
index 5b77c590..ea10dca 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsCallbackInterfaceInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsCallbackInterfaceInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
index 8bb960b..eae8530 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -53,6 +59,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -63,7 +70,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -77,6 +86,37 @@
 
 namespace {
 
+class MozjsConditionalInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsConditionalInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsConditionalInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsConditionalInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsConditionalInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -113,7 +153,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ConditionalInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -132,18 +173,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->enabled_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConditionalInterface* impl =
+      wrapper_private->wrappable<ConditionalInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->enabled_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_enabledAttribute(
@@ -151,18 +195,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConditionalInterface* impl =
+      wrapper_private->wrappable<ConditionalInterface>().get();
   TypeTraits<int32_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
+
   impl->set_enabled_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 #endif  // ENABLE_CONDITIONAL_PROPERTY
@@ -172,18 +219,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->disabled_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConditionalInterface* impl =
+      wrapper_private->wrappable<ConditionalInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->disabled_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_disabledAttribute(
@@ -191,27 +241,28 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConditionalInterface* impl =
+      wrapper_private->wrappable<ConditionalInterface>().get();
   TypeTraits<int32_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
+
   impl->set_disabled_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 #endif  // NO_ENABLE_CONDITIONAL_PROPERTY
 #if defined(NO_ENABLE_CONDITIONAL_PROPERTY)
 JSBool fcn_disabledOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -224,26 +275,24 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
+      wrapper_private->wrappable<ConditionalInterface>().get();
+
   impl->DisabledOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 #endif  // NO_ENABLE_CONDITIONAL_PROPERTY
 #if defined(ENABLE_CONDITIONAL_PROPERTY)
 JSBool fcn_enabledOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -256,17 +305,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   ConditionalInterface* impl =
-      WrapperPrivate::GetWrappable<ConditionalInterface>(object);
+      wrapper_private->wrappable<ConditionalInterface>().get();
+
   impl->EnabledOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 #endif  // ENABLE_CONDITIONAL_PROPERTY
@@ -317,6 +366,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -336,7 +389,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -356,8 +410,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ConditionalInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ConditionalInterface"));
+  const char name[] =
+      "ConditionalInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -366,8 +421,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -399,7 +459,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsConditionalInterface::CreateInstance(
+JSObject* MozjsConditionalInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -407,8 +467,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsConditionalInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
index 93e67b4..76eae81 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConditionalInterface.h
@@ -40,8 +40,9 @@
 
 class MozjsConditionalInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
index 3648f49..06ca83e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,6 +83,37 @@
 namespace testing {
 
 namespace {
+
+class MozjsConstantsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsConstantsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsConstantsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsConstantsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsConstantsInterfaceHandler>
+    proxy_handler;
+
 JSBool get_INTEGER_CONSTANT(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
@@ -81,11 +121,11 @@
                  ValueForConstantsInterface_kIntegerConstantDoesNotMatchIDL);
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ToJSValue(context, 5, &exception_state, &result_value);
-  if (!exception_state.IsExceptionSet()) {
-     vp.set(result_value);
+  ToJSValue(context, 5, &result_value);
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_DOUBLE_CONSTANT(
@@ -96,11 +136,11 @@
       "the value in the interface definition.";
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ToJSValue(context, 2.718, &exception_state, &result_value);
-  if (!exception_state.IsExceptionSet()) {
-     vp.set(result_value);
+  ToJSValue(context, 2.718, &result_value);
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -140,7 +180,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ConstantsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -190,6 +231,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -209,7 +254,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -229,8 +275,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ConstantsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ConstantsInterface"));
+  const char name[] =
+      "ConstantsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -239,8 +286,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -272,7 +324,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsConstantsInterface::CreateInstance(
+JSObject* MozjsConstantsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -280,8 +332,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsConstantsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
index 3d9384c..fe793ef 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstantsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsConstantsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
index c70a26d..7ca19b8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsConstructorInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsConstructorInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsConstructorInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsConstructorInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsConstructorInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ConstructorInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -139,6 +180,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -158,7 +203,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -178,18 +224,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ConstructorInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ConstructorInterface"));
+  const char name[] =
+      "ConstructorInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -221,7 +283,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsConstructorInterface::CreateInstance(
+JSObject* MozjsConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -229,8 +291,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsConstructorInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -256,11 +329,85 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor1(
+    JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<ConstructorInterface> new_object =
+      new ConstructorInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
+
+JSBool Constructor2(
+    JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<bool >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  scoped_refptr<ConstructorInterface> new_object =
+      new ConstructorInterface(arg);
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
+  return true;
+}
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  switch(argc) {
+    case(0): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return Constructor1(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return Constructor2(
+                  context, argc, vp);
+      }
+      break;
+    }
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  MozjsExceptionState exception_state(context);
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
+}
 }  // namespace
 
 
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
index 12b63d4..d04a69f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsConstructorInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
index d235a17..cdc6b94 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsConstructorWithArgumentsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsConstructorWithArgumentsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsConstructorWithArgumentsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsConstructorWithArgumentsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsConstructorWithArgumentsInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ConstructorWithArgumentsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,18 +172,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ConstructorWithArgumentsInterface* impl =
-      WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->long_arg();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConstructorWithArgumentsInterface* impl =
+      wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->long_arg(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_booleanArg(
@@ -150,18 +194,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ConstructorWithArgumentsInterface* impl =
-      WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->boolean_arg();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConstructorWithArgumentsInterface* impl =
+      wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->boolean_arg(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_stringArg(
@@ -169,18 +216,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ConstructorWithArgumentsInterface* impl =
-      WrapperPrivate::GetWrappable<ConstructorWithArgumentsInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->string_arg();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ConstructorWithArgumentsInterface* impl =
+      wrapper_private->wrappable<ConstructorWithArgumentsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->string_arg(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -214,6 +264,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -233,7 +287,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -253,18 +308,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ConstructorWithArgumentsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ConstructorWithArgumentsInterface"));
+  const char name[] =
+      "ConstructorWithArgumentsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(2);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -296,7 +367,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsConstructorWithArgumentsInterface::CreateInstance(
+JSObject* MozjsConstructorWithArgumentsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -304,8 +375,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsConstructorWithArgumentsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -331,9 +413,64 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  const size_t kMinArguments = 2;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<bool >::ConversionType arg2;
+  // Optional arguments with default values
+  TypeTraits<std::string >::ConversionType default_arg =
+      "default";
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+  size_t num_set_arguments = 3;
+  if (args.length() > 2) {
+    JS::RootedValue optional_value0(
+        context, args[2]);
+    FromJSValue(context,
+                optional_value0,
+                kNoConversionFlags,
+                &exception_state,
+                &default_arg);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+  }
+
+  scoped_refptr<ConstructorWithArgumentsInterface> new_object =
+      new ConstructorWithArgumentsInterface(arg1, arg2, default_arg);
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
index cb43afe..44d36d4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsConstructorWithArgumentsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsConstructorWithArgumentsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
index 1621a7b..bc6eb8b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsDOMStringTestInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsDOMStringTestInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsDOMStringTestInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsDOMStringTestInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsDOMStringTestInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "DOMStringTestInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_property(
@@ -148,18 +192,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
+
   impl->set_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_readOnlyProperty(
@@ -167,18 +214,43 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->read_only_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->read_only_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
+}
+
+JSBool get_readOnlyTokenProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->read_only_token_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullIsEmptyProperty(
@@ -186,18 +258,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->null_is_empty_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->null_is_empty_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullIsEmptyProperty(
@@ -205,18 +280,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagTreatNullAsEmptyString), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
+
   impl->set_null_is_empty_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_undefinedIsEmptyProperty(
@@ -224,18 +302,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->undefined_is_empty_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->undefined_is_empty_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_undefinedIsEmptyProperty(
@@ -243,18 +324,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagTreatUndefinedAsEmptyString), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
+
   impl->set_undefined_is_empty_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableUndefinedIsEmptyProperty(
@@ -262,18 +346,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
-  TypeTraits<base::optional<std::string > >::ReturnType value =
-      impl->nullable_undefined_is_empty_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_undefined_is_empty_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableUndefinedIsEmptyProperty(
@@ -281,18 +368,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DOMStringTestInterface* impl =
+      wrapper_private->wrappable<DOMStringTestInterface>().get();
   TypeTraits<base::optional<std::string > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable | kConversionFlagTreatUndefinedAsEmptyString), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DOMStringTestInterface* impl =
-      WrapperPrivate::GetWrappable<DOMStringTestInterface>(object);
+
   impl->set_nullable_undefined_is_empty_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -309,6 +399,12 @@
       JSOP_WRAPPER(&get_readOnlyProperty),
       JSOP_NULLWRAPPER,
   },
+  {  // Readonly attribute
+      "readOnlyTokenProperty", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY,
+      JSOP_WRAPPER(&get_readOnlyTokenProperty),
+      JSOP_NULLWRAPPER,
+  },
   {  // Read/Write property
       "nullIsEmptyProperty", 0,
       JSPROP_SHARED | JSPROP_ENUMERATE,
@@ -338,6 +434,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -357,7 +457,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -377,8 +478,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "DOMStringTestInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "DOMStringTestInterface"));
+  const char name[] =
+      "DOMStringTestInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -387,8 +489,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -420,7 +527,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsDOMStringTestInterface::CreateInstance(
+JSObject* MozjsDOMStringTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -428,8 +535,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsDOMStringTestInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
index a6b0007..0cde0d8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDOMStringTestInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsDOMStringTestInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
index cbca054..7770e5c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,219 @@
 
 namespace {
 
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->AnonymousNamedGetter(property_name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->AnonymousNamedSetter(property_name, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->DerivedIndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<uint32_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->DerivedIndexedSetter(index, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsDerivedGetterSetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsDerivedGetterSetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsDerivedGetterSetterInterfaceHandler::named_property_hooks = {
+  IsSupportedNamedProperty,
+  EnumerateSupportedNames,
+  GetNamedProperty,
+  SetNamedProperty,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsDerivedGetterSetterInterfaceHandler::indexed_property_hooks = {
+  IsSupportedIndexProperty,
+  EnumerateSupportedIndexes,
+  GetIndexedProperty,
+  SetIndexedProperty,
+  NULL,
+};
+
+static base::LazyInstance<MozjsDerivedGetterSetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +333,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "DerivedGetterSetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +352,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->length();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->length(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_propertyOnDerivedClass(
@@ -148,18 +374,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->property_on_derived_class();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->property_on_derived_class(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_propertyOnDerivedClass(
@@ -167,25 +396,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
   TypeTraits<bool >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
+
   impl->set_property_on_derived_class(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_derivedIndexedGetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -198,40 +428,47 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->DerivedIndexedGetter(index);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->DerivedIndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_derivedIndexedSetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -244,44 +481,53 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedGetterSetterInterface* impl =
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<uint32_t >::ConversionType value;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &value);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
   impl->DerivedIndexedSetter(index, value);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_operationOnDerivedClass(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -294,17 +540,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   DerivedGetterSetterInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedGetterSetterInterface>(object);
+      wrapper_private->wrappable<DerivedGetterSetterInterface>().get();
+
   impl->OperationOnDerivedClass();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -353,6 +599,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -372,7 +622,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -392,8 +643,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "DerivedGetterSetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "DerivedGetterSetterInterface"));
+  const char name[] =
+      "DerivedGetterSetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -402,8 +654,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -435,7 +692,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsDerivedGetterSetterInterface::CreateInstance(
+JSObject* MozjsDerivedGetterSetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -443,8 +700,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsDerivedGetterSetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
index 3aeb1ad..6913c19 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedGetterSetterInterface.h
@@ -39,8 +39,9 @@
 
 class MozjsDerivedGetterSetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
index 2112c3d..96a27ce 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,38 @@
 
 namespace {
 
+class MozjsDerivedInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsDerivedInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsDerivedInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsDerivedInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsDerivedInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "DerivedInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -121,6 +163,7 @@
   interface_object_class->enumerate = JS_EnumerateStub;
   interface_object_class->resolve = JS_ResolveStub;
   interface_object_class->convert = JS_ConvertStub;
+  interface_object_class->construct = Constructor;
   return interface_data;
 }
 
@@ -129,25 +172,26 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DerivedInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->derived_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DerivedInterface* impl =
+      wrapper_private->wrappable<DerivedInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->derived_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_derivedOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -160,17 +204,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   DerivedInterface* impl =
-      WrapperPrivate::GetWrappable<DerivedInterface>(object);
+      wrapper_private->wrappable<DerivedInterface>().get();
+
   impl->DerivedOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -199,6 +243,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -218,7 +266,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -238,18 +287,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "DerivedInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "DerivedInterface"));
+  const char name[] =
+      "DerivedInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -281,7 +346,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsDerivedInterface::CreateInstance(
+JSObject* MozjsDerivedInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -289,8 +354,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsDerivedInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -316,6 +392,19 @@
 
 
 namespace {
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<DerivedInterface> new_object =
+      new DerivedInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
+  return true;
+}
 }  // namespace
 
 
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
index 328c87b..59beb06 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDerivedInterface.h
@@ -39,8 +39,9 @@
 
 class MozjsDerivedInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
index 862c849..baf4573 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -53,6 +59,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -63,7 +70,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -77,6 +86,37 @@
 
 namespace {
 
+class MozjsDisabledInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsDisabledInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsDisabledInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsDisabledInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsDisabledInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -113,7 +153,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "DisabledInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,18 +172,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  DisabledInterface* impl =
-      WrapperPrivate::GetWrappable<DisabledInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->disabled_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DisabledInterface* impl =
+      wrapper_private->wrappable<DisabledInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->disabled_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_disabledProperty(
@@ -150,25 +194,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  DisabledInterface* impl =
+      wrapper_private->wrappable<DisabledInterface>().get();
   TypeTraits<int32_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  DisabledInterface* impl =
-      WrapperPrivate::GetWrappable<DisabledInterface>(object);
+
   impl->set_disabled_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_disabledFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -181,17 +226,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   DisabledInterface* impl =
-      WrapperPrivate::GetWrappable<DisabledInterface>(object);
+      wrapper_private->wrappable<DisabledInterface>().get();
+
   impl->DisabledFunction();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -220,6 +265,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -239,7 +288,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -259,8 +309,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "DisabledInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "DisabledInterface"));
+  const char name[] =
+      "DisabledInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -269,8 +320,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -302,7 +358,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsDisabledInterface::CreateInstance(
+JSObject* MozjsDisabledInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -310,8 +366,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsDisabledInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
index 6b5f628..360c946 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsDisabledInterface.h
@@ -40,8 +40,9 @@
 
 class MozjsDisabledInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
index 8255e6f..2ed75aa 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,12 +68,23 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::WrapperFactory;
 using cobalt::script::Wrappable;
+// Declare and define these in the same namespace that the other overloads
+// were brought into with the using declaration.
+void ToJSValue(
+    JSContext* context,
+    EnumerationInterface::TestEnum in_enum,
+    JS::MutableHandleValue out_value);
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 EnumerationInterface::TestEnum* out_enum);
 }  // namespace
 
 namespace cobalt {
@@ -74,7 +92,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsEnumerationInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsEnumerationInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsEnumerationInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsEnumerationInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsEnumerationInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +161,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "EnumerationInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,18 +181,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  EnumerationInterface* impl =
-      WrapperPrivate::GetWrappable<EnumerationInterface>(object);
-  TypeTraits<EnumerationInterface::TestEnum >::ReturnType value =
-      impl->enum_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  EnumerationInterface* impl =
+      wrapper_private->wrappable<EnumerationInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->enum_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_enumProperty(
@@ -150,18 +203,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  EnumerationInterface* impl =
+      wrapper_private->wrappable<EnumerationInterface>().get();
   TypeTraits<EnumerationInterface::TestEnum >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  EnumerationInterface* impl =
-      WrapperPrivate::GetWrappable<EnumerationInterface>(object);
+
   impl->set_enum_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -183,6 +239,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -202,7 +262,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -222,18 +283,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "EnumerationInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "EnumerationInterface"));
+  const char name[] =
+      "EnumerationInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -265,7 +342,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsEnumerationInterface::CreateInstance(
+JSObject* MozjsEnumerationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -273,8 +350,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsEnumerationInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -300,9 +388,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<EnumerationInterface> new_object =
+      new EnumerationInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
@@ -313,4 +409,55 @@
 }  // namespace cobalt
 
 namespace {
+
+inline void ToJSValue(
+    JSContext* context,
+    EnumerationInterface::TestEnum in_enum,
+    JS::MutableHandleValue out_value) {
+
+  switch (in_enum) {
+    case EnumerationInterface::kAlpha:
+      ToJSValue(context, std::string("alpha"), out_value);
+      return;
+    case EnumerationInterface::kBeta:
+      ToJSValue(context, std::string("beta"), out_value);
+      return;
+    case EnumerationInterface::kGamma:
+      ToJSValue(context, std::string("gamma"), out_value);
+      return;
+  }
+}
+
+
+inline void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 EnumerationInterface::TestEnum* out_enum) {
+  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
+  // JSValue -> IDL enum algorithm described here:
+  // http://heycam.github.io/webidl/#es-enumeration
+  // 1. Let S be the result of calling ToString(V).
+  JS::RootedString rooted_string(context, JS_ValueToString(context, value));
+
+  JSBool match = JS_FALSE;
+// 3. Return the enumeration value of type E that is equal to S.
+if (JS_StringEqualsAscii(
+      context, rooted_string, "alpha", &match)
+      && match) {
+    *out_enum = EnumerationInterface::kAlpha;
+  } else if (JS_StringEqualsAscii(
+      context, rooted_string, "beta", &match)
+      && match) {
+    *out_enum = EnumerationInterface::kBeta;
+  } else if (JS_StringEqualsAscii(
+      context, rooted_string, "gamma", &match)
+      && match) {
+    *out_enum = EnumerationInterface::kGamma;
+  } else {
+    // 2. If S is not one of E's enumeration values, then throw a TypeError.
+    exception_state->
+        SetSimpleException(ExceptionState::kTypeError,
+                           "Cannot convert JavaScript value to Enum.");
+    return;
+  }
+}
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
index 20b7fcc..b4b3e19 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsEnumerationInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsEnumerationInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
index 39285e8..498e223 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsExceptionObjectInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsExceptionObjectInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsExceptionObjectInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsExceptionObjectInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsExceptionObjectInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ExceptionObjectInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ExceptionObjectInterface* impl =
-      WrapperPrivate::GetWrappable<ExceptionObjectInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->error();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ExceptionObjectInterface* impl =
+      wrapper_private->wrappable<ExceptionObjectInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->error(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_message(
@@ -148,18 +192,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ExceptionObjectInterface* impl =
-      WrapperPrivate::GetWrappable<ExceptionObjectInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->message();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ExceptionObjectInterface* impl =
+      wrapper_private->wrappable<ExceptionObjectInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->message(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -187,6 +234,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -206,7 +257,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -226,8 +278,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ExceptionObjectInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ExceptionObjectInterface"));
+  const char name[] =
+      "ExceptionObjectInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -236,8 +289,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -269,7 +327,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsExceptionObjectInterface::CreateInstance(
+JSObject* MozjsExceptionObjectInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -277,8 +335,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsExceptionObjectInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
index 747e528..0ba0055 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionObjectInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsExceptionObjectInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
index dc19788..21cbe31 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsExceptionsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsExceptionsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsExceptionsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsExceptionsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsExceptionsInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ExceptionsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,18 +172,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ExceptionsInterface* impl =
-      WrapperPrivate::GetWrappable<ExceptionsInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->attribute_throws_exception(&exception_state);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ExceptionsInterface* impl =
+      wrapper_private->wrappable<ExceptionsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->attribute_throws_exception(&exception_state),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_attributeThrowsException(
@@ -150,25 +194,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ExceptionsInterface* impl =
+      wrapper_private->wrappable<ExceptionsInterface>().get();
   TypeTraits<bool >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ExceptionsInterface* impl =
-      WrapperPrivate::GetWrappable<ExceptionsInterface>(object);
+
   impl->set_attribute_throws_exception(value, &exception_state);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_functionThrowsException(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -181,17 +226,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   ExceptionsInterface* impl =
-      WrapperPrivate::GetWrappable<ExceptionsInterface>(object);
+      wrapper_private->wrappable<ExceptionsInterface>().get();
+
   impl->FunctionThrowsException(&exception_state);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -220,6 +265,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -239,7 +288,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -259,18 +309,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ExceptionsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ExceptionsInterface"));
+  const char name[] =
+      "ExceptionsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -302,7 +368,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsExceptionsInterface::CreateInstance(
+JSObject* MozjsExceptionsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -310,8 +376,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsExceptionsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -337,9 +414,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<ExceptionsInterface> new_object =
+      new ExceptionsInterface(&exception_state);
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
index f85051d..b5fe100 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExceptionsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsExceptionsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
index a9c4572..06bcf72 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsExtendedIDLAttributesInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsExtendedIDLAttributesInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsExtendedIDLAttributesInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsExtendedIDLAttributesInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsExtendedIDLAttributesInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ExtendedIDLAttributesInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -126,9 +167,7 @@
 
 JSBool fcn_callWithSettings(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -141,19 +180,19 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ExtendedIDLAttributesInterface* impl =
+      wrapper_private->wrappable<ExtendedIDLAttributesInterface>().get();
   MozjsGlobalObjectProxy* global_object_proxy =
       static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  ExtendedIDLAttributesInterface* impl =
-      WrapperPrivate::GetWrappable<ExtendedIDLAttributesInterface>(object);
+
   impl->CallWithSettings(global_object_proxy->GetEnvironmentSettings());
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -176,6 +215,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -195,7 +238,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -215,8 +259,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ExtendedIDLAttributesInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ExtendedIDLAttributesInterface"));
+  const char name[] =
+      "ExtendedIDLAttributesInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -225,8 +270,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -258,7 +308,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsExtendedIDLAttributesInterface::CreateInstance(
+JSObject* MozjsExtendedIDLAttributesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -266,8 +316,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsExtendedIDLAttributesInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
index de023e6..68909d5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsExtendedIDLAttributesInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsExtendedIDLAttributesInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
index 859f695..fbfc60a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsGetOpaqueRootInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsGetOpaqueRootInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsGetOpaqueRootInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsGetOpaqueRootInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsGetOpaqueRootInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "GetOpaqueRootInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -139,6 +180,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -158,7 +203,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -178,18 +224,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "GetOpaqueRootInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "GetOpaqueRootInterface"));
+  const char name[] =
+      "GetOpaqueRootInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -221,7 +283,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsGetOpaqueRootInterface::CreateInstance(
+JSObject* MozjsGetOpaqueRootInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -229,8 +291,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsGetOpaqueRootInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -256,9 +329,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<GetOpaqueRootInterface> new_object =
+      new GetOpaqueRootInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
index da38f15..343e465 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGetOpaqueRootInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsGetOpaqueRootInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
index a1f623b..27e94db 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsGlobalInterfaceParentHandler : public ProxyHandler {
+ public:
+  MozjsGlobalInterfaceParentHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsGlobalInterfaceParentHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsGlobalInterfaceParentHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsGlobalInterfaceParentHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "GlobalInterfaceParentConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -126,9 +167,7 @@
 
 JSBool fcn_parentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -141,17 +180,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   GlobalInterfaceParent* impl =
-      WrapperPrivate::GetWrappable<GlobalInterfaceParent>(object);
+      wrapper_private->wrappable<GlobalInterfaceParent>().get();
+
   impl->ParentOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -174,6 +213,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -193,7 +236,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -213,8 +257,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "GlobalInterfaceParent";
-  name_value.setString(JS_NewStringCopyZ(context, "GlobalInterfaceParent"));
+  const char name[] =
+      "GlobalInterfaceParent";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -223,8 +268,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -256,7 +306,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsGlobalInterfaceParent::CreateInstance(
+JSObject* MozjsGlobalInterfaceParent::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -264,8 +314,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsGlobalInterfaceParent::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
index c81bb0a..0ed43cb 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsGlobalInterfaceParent.h
@@ -38,8 +38,9 @@
 
 class MozjsGlobalInterfaceParent {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
index 054c19a..e67543f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,143 @@
 
 namespace {
 
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->IndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<uint32_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->IndexedSetter(index, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+bool DeleteIndexedProperty(
+    JSContext* context, JS::HandleObject object, uint32_t index) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+
+  impl->IndexedDeleter(index);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsIndexedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsIndexedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsIndexedGetterInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsIndexedGetterInterfaceHandler::indexed_property_hooks = {
+  IsSupportedIndexProperty,
+  EnumerateSupportedIndexes,
+  GetIndexedProperty,
+  SetIndexedProperty,
+  DeleteIndexedProperty,
+};
+
+static base::LazyInstance<MozjsIndexedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +257,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "IndexedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,25 +276,26 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  IndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<IndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->length();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->length(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
-JSBool fcn_indexedGetter(
+JSBool fcn_indexedDeleter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -160,40 +308,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  IndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<IndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->IndexedGetter(index);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  impl->IndexedDeleter(index);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
-JSBool fcn_indexedSetter(
+JSBool fcn_indexedGetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -206,37 +355,101 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<uint32_t >::ConversionType index;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->IndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    args.rval().set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_indexedSetter(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  IndexedGetterInterface* impl =
+      wrapper_private->wrappable<IndexedGetterInterface>().get();
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<uint32_t >::ConversionType value;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &value);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  IndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<IndexedGetterInterface>(object);
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
   impl->IndexedSetter(index, value);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -252,6 +465,13 @@
 
 const JSFunctionSpec prototype_functions[] = {
   {
+      "indexedDeleter",
+      JSOP_WRAPPER(&fcn_indexedDeleter),
+      1,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
       "indexedGetter",
       JSOP_WRAPPER(&fcn_indexedGetter),
       1,
@@ -272,6 +492,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -291,7 +515,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -311,8 +536,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "IndexedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "IndexedGetterInterface"));
+  const char name[] =
+      "IndexedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -321,8 +547,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -354,7 +585,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsIndexedGetterInterface::CreateInstance(
+JSObject* MozjsIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -362,8 +593,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsIndexedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
index 3b2300b..a61619c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsIndexedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsIndexedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
index 274bea7..5831dae 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsInterfaceWithUnsupportedPropertiesHandler : public ProxyHandler {
+ public:
+  MozjsInterfaceWithUnsupportedPropertiesHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsInterfaceWithUnsupportedPropertiesHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsInterfaceWithUnsupportedPropertiesHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsInterfaceWithUnsupportedPropertiesHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "InterfaceWithUnsupportedPropertiesConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  InterfaceWithUnsupportedProperties* impl =
-      WrapperPrivate::GetWrappable<InterfaceWithUnsupportedProperties>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->supported_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  InterfaceWithUnsupportedProperties* impl =
+      wrapper_private->wrappable<InterfaceWithUnsupportedProperties>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->supported_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -162,6 +206,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -181,7 +229,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -201,8 +250,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "InterfaceWithUnsupportedProperties";
-  name_value.setString(JS_NewStringCopyZ(context, "InterfaceWithUnsupportedProperties"));
+  const char name[] =
+      "InterfaceWithUnsupportedProperties";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -211,8 +261,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -244,7 +299,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsInterfaceWithUnsupportedProperties::CreateInstance(
+JSObject* MozjsInterfaceWithUnsupportedProperties::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -252,8 +307,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsInterfaceWithUnsupportedProperties::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
index 06a8adb..417e204 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsInterfaceWithUnsupportedProperties.h
@@ -38,8 +38,9 @@
 
 class MozjsInterfaceWithUnsupportedProperties {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
index 284f86b..f0a1359 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -74,7 +83,38 @@
 namespace testing {
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
+
+class MozjsNamedConstructorInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNamedConstructorInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNamedConstructorInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNamedConstructorInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNamedConstructorInterfaceHandler>
+    proxy_handler;
+
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -112,7 +152,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NamedConstructorInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -139,6 +180,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -158,7 +203,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -178,18 +224,34 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "SomeNamedConstructor";
-  name_value.setString(JS_NewStringCopyZ(context, "NamedConstructorInterface"));
+  const char name[] =
+      "SomeNamedConstructor";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
 
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32(0);
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -221,7 +283,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNamedConstructorInterface::CreateInstance(
+JSObject* MozjsNamedConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -229,8 +291,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNamedConstructorInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -256,9 +329,17 @@
 
 
 namespace {
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+
+  scoped_refptr<NamedConstructorInterface> new_object =
+      new NamedConstructorInterface();
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
   return true;
 }
 }  // namespace
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
index 297534c..670e6fc 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedConstructorInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNamedConstructorInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
index 4c4bf01..d9debc4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,143 @@
 
 namespace {
 
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NamedGetter(property_name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->NamedSetter(property_name, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+bool DeleteNamedProperty(JSContext* context, JS::HandleObject object,
+                         const std::string& property_name) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
+
+  impl->NamedDeleter(property_name);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsNamedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNamedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNamedGetterInterfaceHandler::named_property_hooks = {
+  IsSupportedNamedProperty,
+  EnumerateSupportedNames,
+  GetNamedProperty,
+  SetNamedProperty,
+  DeleteNamedProperty,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNamedGetterInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNamedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +257,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NamedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -126,9 +273,7 @@
 
 JSBool fcn_namedDeleter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -141,37 +286,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<std::string >::ConversionType name;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &name);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &name);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedGetterInterface>(object);
+
   impl->NamedDeleter(name);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_namedGetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -184,40 +333,47 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<std::string >::ConversionType name;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &name);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &name);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedGetterInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->NamedGetter(name);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NamedGetter(name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_namedSetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -230,37 +386,48 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedGetterInterface* impl =
+      wrapper_private->wrappable<NamedGetterInterface>().get();
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<std::string >::ConversionType name;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &name);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<std::string >::ConversionType value;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &value);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &name);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedGetterInterface>(object);
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
   impl->NamedSetter(name, value);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -297,6 +464,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -316,7 +487,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -336,8 +508,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NamedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NamedGetterInterface"));
+  const char name[] =
+      "NamedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -346,8 +519,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -379,7 +557,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNamedGetterInterface::CreateInstance(
+JSObject* MozjsNamedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -387,8 +565,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNamedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
index cd2035f..613c1b9 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNamedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
index f8d0d7b..e63ec48 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,219 @@
 
 namespace {
 
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NamedGetter(property_name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->NamedSetter(property_name, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->IndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<uint32_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->IndexedSetter(index, value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+class MozjsNamedIndexedGetterInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNamedIndexedGetterInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNamedIndexedGetterInterfaceHandler::named_property_hooks = {
+  IsSupportedNamedProperty,
+  EnumerateSupportedNames,
+  GetNamedProperty,
+  SetNamedProperty,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNamedIndexedGetterInterfaceHandler::indexed_property_hooks = {
+  IsSupportedIndexProperty,
+  EnumerateSupportedIndexes,
+  GetIndexedProperty,
+  SetIndexedProperty,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNamedIndexedGetterInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +333,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NamedIndexedGetterInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +352,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->length();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->length(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_propertyOnBaseClass(
@@ -148,18 +374,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
-  TypeTraits<bool >::ReturnType value =
-      impl->property_on_base_class();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->property_on_base_class(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_propertyOnBaseClass(
@@ -167,25 +396,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
   TypeTraits<bool >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
+
   impl->set_property_on_base_class(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_indexedGetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -198,40 +428,47 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->IndexedGetter(index);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->IndexedGetter(index),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_indexedSetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -244,44 +481,53 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType index;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &index);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<uint32_t >::ConversionType value;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &value);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &index);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
   impl->IndexedSetter(index, value);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_namedGetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -294,40 +540,47 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<std::string >::ConversionType name;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &name);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &name);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->NamedGetter(name);
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NamedGetter(name),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_namedSetter(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -340,44 +593,53 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NamedIndexedGetterInterface* impl =
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<std::string >::ConversionType name;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &name);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<std::string >::ConversionType value;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &value);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &name);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
   impl->NamedSetter(name, value);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_operationOnBaseClass(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -390,17 +652,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NamedIndexedGetterInterface* impl =
-      WrapperPrivate::GetWrappable<NamedIndexedGetterInterface>(object);
+      wrapper_private->wrappable<NamedIndexedGetterInterface>().get();
+
   impl->OperationOnBaseClass();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -463,6 +725,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -482,7 +748,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -502,8 +769,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NamedIndexedGetterInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NamedIndexedGetterInterface"));
+  const char name[] =
+      "NamedIndexedGetterInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -512,8 +780,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -545,7 +818,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNamedIndexedGetterInterface::CreateInstance(
+JSObject* MozjsNamedIndexedGetterInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -553,8 +826,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNamedIndexedGetterInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
index b0a15cc..d0cc78a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNamedIndexedGetterInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNamedIndexedGetterInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
index 43a0e5c..e665fea 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/put_forwards_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsNestedPutForwardsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNestedPutForwardsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNestedPutForwardsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNestedPutForwardsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNestedPutForwardsInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NestedPutForwardsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +174,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NestedPutForwardsInterface* impl =
-      WrapperPrivate::GetWrappable<NestedPutForwardsInterface>(object);
-  TypeTraits<scoped_refptr<PutForwardsInterface> >::ReturnType value =
-      impl->nested_forwarding_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NestedPutForwardsInterface* impl =
+      wrapper_private->wrappable<NestedPutForwardsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nested_forwarding_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nestedForwardingAttribute(
@@ -152,14 +196,43 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  TypeTraits<scoped_refptr<PutForwardsInterface> >::ConversionType value;
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NestedPutForwardsInterface* impl =
+      wrapper_private->wrappable<NestedPutForwardsInterface>().get();
+  { // Begin scope of scoped_refptr<PutForwardsInterface> forwarded_impl.
+    scoped_refptr<PutForwardsInterface> forwarded_impl =
+       impl->nested_forwarding_attribute();
+    if (!forwarded_impl) {
+      NOTREACHED();
+      return false;
+    }
+    if (!exception_state.is_exception_set()) {
+  { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl.
+    scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl =
+       forwarded_impl->forwarding_attribute();
+    if (!forwarded_forwarded_impl) {
+      NOTREACHED();
+      return false;
+    }
+    if (!exception_state.is_exception_set()) {
+  TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NOTIMPLEMENTED();
-  return !exception_state.IsExceptionSet();
+
+  forwarded_forwarded_impl->set_arbitrary_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+    return !exception_state.is_exception_set();
+  } // End scope of scoped_refptr<ArbitraryInterface> forwarded_forwarded_impl.
+}
+    return !exception_state.is_exception_set();
+  } // End scope of scoped_refptr<PutForwardsInterface> forwarded_impl.
 }
 
 
@@ -181,6 +254,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -200,7 +277,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -220,8 +298,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NestedPutForwardsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NestedPutForwardsInterface"));
+  const char name[] =
+      "NestedPutForwardsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -230,8 +309,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -263,7 +347,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNestedPutForwardsInterface::CreateInstance(
+JSObject* MozjsNestedPutForwardsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -271,8 +355,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNestedPutForwardsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
index 899b2b9..47b1965 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNestedPutForwardsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNestedPutForwardsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
index fa03c71..ecf9e98 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsNoConstructorInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNoConstructorInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNoConstructorInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNoConstructorInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNoConstructorInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NoConstructorInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -137,6 +178,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -156,7 +201,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -176,8 +222,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NoConstructorInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NoConstructorInterface"));
+  const char name[] =
+      "NoConstructorInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -186,8 +233,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -219,7 +271,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNoConstructorInterface::CreateInstance(
+JSObject* MozjsNoConstructorInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -227,8 +279,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNoConstructorInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
index a7da004..1c2a1c8 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoConstructorInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNoConstructorInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
index 780ecb1..27d50a2 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsNoInterfaceObjectInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNoInterfaceObjectInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNoInterfaceObjectInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNoInterfaceObjectInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNoInterfaceObjectInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NoInterfaceObjectInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -137,6 +178,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -156,7 +201,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -185,7 +231,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNoInterfaceObjectInterface::CreateInstance(
+JSObject* MozjsNoInterfaceObjectInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -193,8 +239,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNoInterfaceObjectInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
index c44bc47..8d5c0f1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNoInterfaceObjectInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNoInterfaceObjectInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
 };
 
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
index 95629dc..3176045 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsNullableTypesTestInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNullableTypesTestInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNullableTypesTestInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNullableTypesTestInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNullableTypesTestInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NullableTypesTestInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +174,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<bool > >::ReturnType value =
-      impl->nullable_boolean_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_boolean_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableBooleanProperty(
@@ -152,18 +196,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   TypeTraits<base::optional<bool > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->set_nullable_boolean_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableNumericProperty(
@@ -171,18 +218,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<int32_t > >::ReturnType value =
-      impl->nullable_numeric_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_numeric_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableNumericProperty(
@@ -190,18 +240,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   TypeTraits<base::optional<int32_t > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->set_nullable_numeric_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableStringProperty(
@@ -209,18 +262,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<std::string > >::ReturnType value =
-      impl->nullable_string_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_string_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableStringProperty(
@@ -228,18 +284,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   TypeTraits<base::optional<std::string > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->set_nullable_string_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableObjectProperty(
@@ -247,18 +306,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value =
-      impl->nullable_object_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_object_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableObjectProperty(
@@ -266,25 +328,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->set_nullable_object_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableBooleanArgument(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -297,37 +360,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<base::optional<bool > >::ConversionType arg;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagNullable), &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagNullable),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->NullableBooleanArgument(arg);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableBooleanOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -340,27 +407,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<bool > >::ReturnType value =
-      impl->NullableBooleanOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NullableBooleanOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableNumericArgument(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -373,37 +441,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<base::optional<int32_t > >::ConversionType arg;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagNullable), &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagNullable),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->NullableNumericArgument(arg);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableNumericOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -416,27 +488,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<int32_t > >::ReturnType value =
-      impl->NullableNumericOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NullableNumericOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableObjectArgument(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -449,37 +522,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagNullable), &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagNullable),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->NullableObjectArgument(arg);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableObjectOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -492,27 +569,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value =
-      impl->NullableObjectOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NullableObjectOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableStringArgument(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -525,37 +603,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NullableTypesTestInterface* impl =
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<base::optional<std::string > >::ConversionType arg;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagNullable), &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagNullable),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
+
   impl->NullableStringArgument(arg);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_nullableStringOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -568,20 +650,23 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NullableTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NullableTypesTestInterface>(object);
-  TypeTraits<base::optional<std::string > >::ReturnType value =
-      impl->NullableStringOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NullableTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->NullableStringOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -677,6 +762,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -696,7 +785,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -716,8 +806,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NullableTypesTestInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NullableTypesTestInterface"));
+  const char name[] =
+      "NullableTypesTestInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -726,8 +817,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -759,7 +855,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNullableTypesTestInterface::CreateInstance(
+JSObject* MozjsNullableTypesTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -767,8 +863,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNullableTypesTestInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
index 95895b7..69bfddd 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNullableTypesTestInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNullableTypesTestInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
index ce72076..bfa31b4 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsNumericTypesTestInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsNumericTypesTestInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsNumericTypesTestInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsNumericTypesTestInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsNumericTypesTestInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "NumericTypesTestInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int8_t >::ReturnType value =
-      impl->byte_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->byte_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_byteProperty(
@@ -148,18 +192,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<int8_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_byte_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_octetProperty(
@@ -167,18 +214,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint8_t >::ReturnType value =
-      impl->octet_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->octet_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_octetProperty(
@@ -186,18 +236,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<uint8_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_octet_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_shortProperty(
@@ -205,18 +258,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int16_t >::ReturnType value =
-      impl->short_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->short_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_shortProperty(
@@ -224,18 +280,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<int16_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_short_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_unsignedShortProperty(
@@ -243,18 +302,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint16_t >::ReturnType value =
-      impl->unsigned_short_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->unsigned_short_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_unsignedShortProperty(
@@ -262,18 +324,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<uint16_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_unsigned_short_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_longProperty(
@@ -281,18 +346,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->long_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->long_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_longProperty(
@@ -300,18 +368,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<int32_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_long_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_unsignedLongProperty(
@@ -319,18 +390,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->unsigned_long_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->unsigned_long_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_unsignedLongProperty(
@@ -338,18 +412,109 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<uint32_t >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_unsigned_long_property(value);
   result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
 
-  return !exception_state.IsExceptionSet();
+JSBool get_longLongProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->long_long_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool set_longLongProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+  TypeTraits<int64_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->set_long_long_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool get_unsignedLongLongProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->unsigned_long_long_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool set_unsignedLongLongProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+  TypeTraits<uint64_t >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->set_unsigned_long_long_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_doubleProperty(
@@ -357,18 +522,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<double >::ReturnType value =
-      impl->double_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->double_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_doubleProperty(
@@ -376,18 +544,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<double >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagRestricted), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_double_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_unrestrictedDoubleProperty(
@@ -395,18 +566,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<double >::ReturnType value =
-      impl->unrestricted_double_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->unrestricted_double_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_unrestrictedDoubleProperty(
@@ -414,25 +588,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   TypeTraits<double >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->set_unrestricted_double_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_byteArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -445,37 +620,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<int8_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->ByteArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_byteReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -488,27 +667,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int8_t >::ReturnType value =
-      impl->ByteReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->ByteReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_doubleArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -521,37 +701,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<double >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagRestricted), &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagRestricted),
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->DoubleArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_doubleReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -564,27 +748,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<double >::ReturnType value =
-      impl->DoubleReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->DoubleReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_longArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -597,37 +782,122 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<int32_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->LongArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
 
-  if (!exception_state.IsExceptionSet()) {
+JSBool fcn_longLongArgumentOperation(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int64_t >::ConversionType arg1;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->LongLongArgumentOperation(arg1);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_longLongReturnOperation(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->LongLongReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_longReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -640,27 +910,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->LongReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->LongReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_octetArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -673,37 +944,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint8_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->OctetArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_octetReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -716,27 +991,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint8_t >::ReturnType value =
-      impl->OctetReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->OctetReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_shortArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -749,37 +1025,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<int16_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->ShortArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_shortReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -792,27 +1072,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<int16_t >::ReturnType value =
-      impl->ShortReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->ShortReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unrestrictedDoubleArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -825,37 +1106,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<double >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->UnrestrictedDoubleArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unrestrictedDoubleReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -868,27 +1153,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<double >::ReturnType value =
-      impl->UnrestrictedDoubleReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->UnrestrictedDoubleReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unsignedLongArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -901,37 +1187,122 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint32_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->UnsignedLongArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
 
-  if (!exception_state.IsExceptionSet()) {
+JSBool fcn_unsignedLongLongArgumentOperation(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<uint64_t >::ConversionType arg1;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->UnsignedLongLongArgumentOperation(arg1);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_unsignedLongLongReturnOperation(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->UnsignedLongLongReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unsignedLongReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -944,27 +1315,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint32_t >::ReturnType value =
-      impl->UnsignedLongReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->UnsignedLongReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unsignedShortArgumentOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -977,37 +1349,41 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  NumericTypesTestInterface* impl =
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<uint16_t >::ConversionType arg1;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
+
   impl->UnsignedShortArgumentOperation(arg1);
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_unsignedShortReturnOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -1020,20 +1396,23 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   NumericTypesTestInterface* impl =
-      WrapperPrivate::GetWrappable<NumericTypesTestInterface>(object);
-  TypeTraits<uint16_t >::ReturnType value =
-      impl->UnsignedShortReturnOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<NumericTypesTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->UnsignedShortReturnOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -1075,6 +1454,18 @@
       JSOP_WRAPPER(&set_unsignedLongProperty),
   },
   {  // Read/Write property
+      "longLongProperty", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&get_longLongProperty),
+      JSOP_WRAPPER(&set_longLongProperty),
+  },
+  {  // Read/Write property
+      "unsignedLongLongProperty", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&get_unsignedLongLongProperty),
+      JSOP_WRAPPER(&set_unsignedLongLongProperty),
+  },
+  {  // Read/Write property
       "doubleProperty", 0,
       JSPROP_SHARED | JSPROP_ENUMERATE,
       JSOP_WRAPPER(&get_doubleProperty),
@@ -1126,6 +1517,20 @@
       NULL,
   },
   {
+      "longLongArgumentOperation",
+      JSOP_WRAPPER(&fcn_longLongArgumentOperation),
+      1,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
+      "longLongReturnOperation",
+      JSOP_WRAPPER(&fcn_longLongReturnOperation),
+      0,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
       "longReturnOperation",
       JSOP_WRAPPER(&fcn_longReturnOperation),
       0,
@@ -1182,6 +1587,20 @@
       NULL,
   },
   {
+      "unsignedLongLongArgumentOperation",
+      JSOP_WRAPPER(&fcn_unsignedLongLongArgumentOperation),
+      1,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
+      "unsignedLongLongReturnOperation",
+      JSOP_WRAPPER(&fcn_unsignedLongLongReturnOperation),
+      0,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  {
       "unsignedLongReturnOperation",
       JSOP_WRAPPER(&fcn_unsignedLongReturnOperation),
       0,
@@ -1209,6 +1628,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -1228,7 +1651,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -1248,8 +1672,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "NumericTypesTestInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "NumericTypesTestInterface"));
+  const char name[] =
+      "NumericTypesTestInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -1258,8 +1683,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -1291,7 +1721,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsNumericTypesTestInterface::CreateInstance(
+JSObject* MozjsNumericTypesTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -1299,8 +1729,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsNumericTypesTestInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
index 696d709..f33342b 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsNumericTypesTestInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsNumericTypesTestInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
index 9fcc745..5e32d87 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.cc
@@ -34,14 +34,20 @@
 #include "cobalt/bindings/testing/derived_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -63,6 +69,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -73,7 +80,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -87,6 +96,37 @@
 
 namespace {
 
+class MozjsObjectTypeBindingsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsObjectTypeBindingsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsObjectTypeBindingsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsObjectTypeBindingsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsObjectTypeBindingsInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -123,7 +163,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "ObjectTypeBindingsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -141,18 +182,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value =
-      impl->arbitrary_object();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->arbitrary_object(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_arbitraryObject(
@@ -160,18 +204,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
   TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
+
   impl->set_arbitrary_object(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_baseInterface(
@@ -179,18 +226,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
-  TypeTraits<scoped_refptr<BaseInterface> >::ReturnType value =
-      impl->base_interface();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->base_interface(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_derivedInterface(
@@ -198,18 +248,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
-  TypeTraits<scoped_refptr<DerivedInterface> >::ReturnType value =
-      impl->derived_interface();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->derived_interface(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_derivedInterface(
@@ -217,18 +270,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
   TypeTraits<scoped_refptr<DerivedInterface> >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
+
   impl->set_derived_interface(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_objectProperty(
@@ -236,18 +292,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
-  TypeTraits<OpaqueHandle >::ReturnType value =
-      impl->object_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->object_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_objectProperty(
@@ -255,18 +314,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  ObjectTypeBindingsInterface* impl =
+      wrapper_private->wrappable<ObjectTypeBindingsInterface>().get();
   TypeTraits<OpaqueHandle >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  ObjectTypeBindingsInterface* impl =
-      WrapperPrivate::GetWrappable<ObjectTypeBindingsInterface>(object);
+
   impl->set_object_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -306,6 +368,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -325,7 +391,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -345,8 +412,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "ObjectTypeBindingsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "ObjectTypeBindingsInterface"));
+  const char name[] =
+      "ObjectTypeBindingsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -355,8 +423,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -388,7 +461,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsObjectTypeBindingsInterface::CreateInstance(
+JSObject* MozjsObjectTypeBindingsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -396,8 +469,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsObjectTypeBindingsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
index 1c53b9c..27aa23c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsObjectTypeBindingsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsObjectTypeBindingsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
index ee67897..473b292 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsOperationsTestInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsOperationsTestInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsOperationsTestInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsOperationsTestInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsOperationsTestInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "OperationsTestInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -130,9 +171,7 @@
 
 JSBool fcn_longFunctionNoArgs(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -145,27 +184,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  TypeTraits<int32_t >::ReturnType value =
-      impl->LongFunctionNoArgs();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<OperationsTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->LongFunctionNoArgs(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_objectFunctionNoArgs(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -178,27 +218,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value =
-      impl->ObjectFunctionNoArgs();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<OperationsTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->ObjectFunctionNoArgs(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_optionalArgumentWithDefault(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -211,37 +252,137 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  // Optional arguments with default values
+  TypeTraits<double >::ConversionType arg1 =
+      2.718;
+  size_t num_set_arguments = 1;
+  if (args.length() > 0) {
+    JS::RootedValue optional_value0(
+        context, args[0]);
+    FromJSValue(context,
+                optional_value0,
+                (kConversionFlagRestricted),
+                &exception_state,
+                &arg1);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+  }
+
+  impl->OptionalArgumentWithDefault(arg1);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_optionalArguments(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
-  TypeTraits<double >::ConversionType arg1;
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  // Optional arguments
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<int32_t >::ConversionType arg3;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagRestricted), &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->OptionalArgumentWithDefault(arg1);
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
+  size_t num_set_arguments = 1;
+  if (args.length() > 1) {
+    JS::RootedValue optional_value0(
+        context, args[1]);
+    FromJSValue(context,
+                optional_value0,
+                kNoConversionFlags,
+                &exception_state,
+                &arg2);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+    ++num_set_arguments;
   }
-  return !exception_state.IsExceptionSet();
+  if (args.length() > 2) {
+    JS::RootedValue optional_value1(
+        context, args[2]);
+    FromJSValue(context,
+                optional_value1,
+                kNoConversionFlags,
+                &exception_state,
+                &arg3);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+    ++num_set_arguments;
+  }
+  switch (num_set_arguments) {
+    case 1:
+      {
+          impl->OptionalArguments(arg1);
+          result_value.set(JS::UndefinedHandleValue);
+          return !exception_state.is_exception_set();
+      }
+      break;
+    case 2:
+      {
+          impl->OptionalArguments(arg1, arg2);
+          result_value.set(JS::UndefinedHandleValue);
+          return !exception_state.is_exception_set();
+      }
+      break;
+    case 3:
+      {
+          impl->OptionalArguments(arg1, arg2, arg3);
+          result_value.set(JS::UndefinedHandleValue);
+          return !exception_state.is_exception_set();
+      }
+      break;
+    default:
+      NOTREACHED();
+      return false;
+  }
 }
 
-JSBool fcn_optionalArguments(
+JSBool fcn_optionalNullableArgumentsWithDefaults(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -254,51 +395,245 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  // Optional arguments with default values
+  TypeTraits<base::optional<bool > >::ConversionType arg1 =
+      base::nullopt;
+  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg2 =
+      NULL;
+  size_t num_set_arguments = 2;
+  if (args.length() > 0) {
+    JS::RootedValue optional_value0(
+        context, args[0]);
+    FromJSValue(context,
+                optional_value0,
+                (kConversionFlagNullable),
+                &exception_state,
+                &arg1);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+  }
+  if (args.length() > 1) {
+    JS::RootedValue optional_value1(
+        context, args[1]);
+    FromJSValue(context,
+                optional_value1,
+                (kConversionFlagNullable),
+                &exception_state,
+                &arg2);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+  }
+
+  impl->OptionalNullableArgumentsWithDefaults(arg1, arg2);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_overloadedFunction1(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+
+  impl->OverloadedFunction();
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_overloadedFunction2(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedFunction(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_overloadedFunction3(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<std::string >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedFunction(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_overloadedFunction4(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
   const size_t kMinArguments = 3;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
+  // Non-optional arguments
   TypeTraits<int32_t >::ConversionType arg1;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<int32_t >::ConversionType arg2;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &arg2);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
   TypeTraits<int32_t >::ConversionType arg3;
-  DCHECK_LT(2, args.length());
-  FromJSValue(context, args.handleAt(2),
-      kNoConversionFlags, &exception_state, &arg3);
-  if (exception_state.IsExceptionSet()) {
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->OptionalArguments(arg1, arg2, arg3);
-  result_value.set(JS::UndefinedHandleValue);
 
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return false;
   }
-  return !exception_state.IsExceptionSet();
+
+  DCHECK_LT(2, args.length());
+  JS::RootedValue non_optional_value2(
+      context, args[2]);
+  FromJSValue(context,
+              non_optional_value2,
+              kNoConversionFlags,
+              &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedFunction(arg1, arg2, arg3);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
-JSBool fcn_optionalNullableArgumentsWithDefaults(
+JSBool fcn_overloadedFunction5(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -311,44 +646,128 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  const size_t kMinArguments = 2;
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 3;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
-  TypeTraits<base::optional<bool > >::ConversionType arg1;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      (kConversionFlagNullable), &exception_state, &arg1);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg2;
-  DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      (kConversionFlagNullable), &exception_state, &arg2);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->OptionalNullableArgumentsWithDefaults(arg1, arg2);
-  result_value.set(JS::UndefinedHandleValue);
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3;
 
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
   }
-  return !exception_state.IsExceptionSet();
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(2, args.length());
+  JS::RootedValue non_optional_value2(
+      context, args[2]);
+  FromJSValue(context,
+              non_optional_value2,
+              kNoConversionFlags,
+              &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedFunction(arg1, arg2, arg3);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_overloadedFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  switch(argc) {
+    case(0): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return fcn_overloadedFunction1(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JS::RootedValue arg(context, args[0]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+      if (arg.isNumber()) {
+        return fcn_overloadedFunction2(
+                  context, argc, vp);
+      }
+      if (true) {
+        return fcn_overloadedFunction3(
+                  context, argc, vp);
+      }
+      if (true) {
+        return fcn_overloadedFunction2(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(3): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JS::RootedValue arg(context, args[2]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+      if (arg.isObject() ? wrapper_factory->DoesObjectImplementInterface(
+              JSVAL_TO_OBJECT(arg), base::GetTypeId<ArbitraryInterface>()) :
+              false) {
+        return fcn_overloadedFunction5(
+                  context, argc, vp);
+      }
+      if (true) {
+        return fcn_overloadedFunction4(
+                  context, argc, vp);
+      }
+      break;
+    }
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
   MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
+}
 
+JSBool fcn_overloadedNullable1(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -361,67 +780,119 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->OverloadedFunction();
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
   }
-  return !exception_state.IsExceptionSet();
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedNullable(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_overloadedNullable2(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<base::optional<bool > >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagNullable),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->OverloadedNullable(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_overloadedNullable(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
-  // Compute the 'this' value.
-  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
-  // 'this' should be an object.
-  JS::RootedObject object(context);
-  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
-    NOTREACHED();
-    return false;
-  }
-  if (!JS_ValueToObject(context, this_value, object.address())) {
-    NOTREACHED();
-    return false;
-  }
-
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  const size_t kMinArguments = 1;
-  if (args.length() < kMinArguments) {
-    exception_state.SetSimpleException(
-        script::ExceptionState::kTypeError, "Not enough arguments.");
-    return false;
+  switch(argc) {
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JS::RootedValue arg(context, args[0]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+      if (arg.isNullOrUndefined()) {
+        return fcn_overloadedNullable2(
+                  context, argc, vp);
+      }
+      if (true) {
+        return fcn_overloadedNullable1(
+                  context, argc, vp);
+      }
+      break;
+    }
   }
-  TypeTraits<int32_t >::ConversionType arg;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->OverloadedNullable(arg);
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  MozjsExceptionState exception_state(context);
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
 }
 
 JSBool fcn_stringFunctionNoArgs(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -434,27 +905,28 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->StringFunctionNoArgs();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<OperationsTestInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->StringFunctionNoArgs(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_variadicPrimitiveArguments(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -467,37 +939,175 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  // Variadic argument
+  TypeTraits<std::vector<int32_t> >::ConversionType bools;
+
+  // Get variadic arguments.
+  const size_t kFirstVariadicArgIndex = 0;
+  if (args.length() > kFirstVariadicArgIndex) {
+    bools.resize(args.length() - kFirstVariadicArgIndex);
+    for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) {
+      JS::RootedValue variadic_argument_value(
+          context, args[i + kFirstVariadicArgIndex]);
+      FromJSValue(context,
+                  variadic_argument_value,
+                  kNoConversionFlags,
+                  &exception_state,
+                  &bools[i]);
+      if (exception_state.is_exception_set()) {
+        return false;
+      }
+    }
+  }
+
+  impl->VariadicPrimitiveArguments(bools);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_variadicStringArgumentsAfterOptionalArgument(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  // Optional arguments
+  TypeTraits<bool >::ConversionType optional_arg;
+  // Variadic argument
+  TypeTraits<std::vector<std::string> >::ConversionType strings;
+  size_t num_set_arguments = 0;
+  if (args.length() > 0) {
+    JS::RootedValue optional_value0(
+        context, args[0]);
+    FromJSValue(context,
+                optional_value0,
+                kNoConversionFlags,
+                &exception_state,
+                &optional_arg);
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+    ++num_set_arguments;
+  }
+
+  // Get variadic arguments.
+  const size_t kLastOptionalArgIndex = 1;
+  if (num_set_arguments == kLastOptionalArgIndex) {
+    // If the last optional argument has been set, we will call the overload
+    // that takes the variadic argument, possibly with an empty vector in the
+    // case that there are no more arguments left.
+    ++num_set_arguments;
+  }
+  const size_t kFirstVariadicArgIndex = 1;
+  if (args.length() > kFirstVariadicArgIndex) {
+    strings.resize(args.length() - kFirstVariadicArgIndex);
+    for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) {
+      JS::RootedValue variadic_argument_value(
+          context, args[i + kFirstVariadicArgIndex]);
+      FromJSValue(context,
+                  variadic_argument_value,
+                  kNoConversionFlags,
+                  &exception_state,
+                  &strings[i]);
+      if (exception_state.is_exception_set()) {
+        return false;
+      }
+    }
+  }
+  switch (num_set_arguments) {
+    case 0:
+      {
+          impl->VariadicStringArgumentsAfterOptionalArgument();
+          result_value.set(JS::UndefinedHandleValue);
+          return !exception_state.is_exception_set();
+      }
+      break;
+    case 2:
+      {
+          impl->VariadicStringArgumentsAfterOptionalArgument(optional_arg, strings);
+          result_value.set(JS::UndefinedHandleValue);
+          return !exception_state.is_exception_set();
+      }
+      break;
+    default:
+      NOTREACHED();
+      return false;
+  }
+}
+
+JSBool fcn_voidFunctionLongArg(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
   const size_t kMinArguments = 1;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
-  TypeTraits<std::vector<int32_t> >::ConversionType bools;
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &bools);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VariadicPrimitiveArguments(bools);
-  result_value.set(JS::UndefinedHandleValue);
 
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  impl->VoidFunctionLongArg(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
-JSBool fcn_variadicStringArgumentsAfterOptionalArgument(
+JSBool fcn_voidFunctionNoArgs(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -510,196 +1120,217 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+
+  impl->VoidFunctionNoArgs();
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_voidFunctionObjectArg(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->VoidFunctionObjectArg(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool fcn_voidFunctionStringArg(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  OperationsTestInterface* impl =
+      wrapper_private->wrappable<OperationsTestInterface>().get();
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<std::string >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->VoidFunctionStringArg(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_overloadedFunction1(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<double >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagRestricted),
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  OperationsTestInterface::OverloadedFunction(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_overloadedFunction2(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
   const size_t kMinArguments = 2;
   if (args.length() < kMinArguments) {
     exception_state.SetSimpleException(
         script::ExceptionState::kTypeError, "Not enough arguments.");
     return false;
   }
-  TypeTraits<bool >::ConversionType optional_arg;
+  // Non-optional arguments
+  TypeTraits<double >::ConversionType arg1;
+  TypeTraits<double >::ConversionType arg2;
+
   DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &optional_arg);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              (kConversionFlagRestricted),
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  TypeTraits<std::vector<std::string> >::ConversionType strings;
+
   DCHECK_LT(1, args.length());
-  FromJSValue(context, args.handleAt(1),
-      kNoConversionFlags, &exception_state, &strings);
-  if (exception_state.IsExceptionSet()) {
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              (kConversionFlagRestricted),
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VariadicStringArgumentsAfterOptionalArgument(optional_arg, strings);
-  result_value.set(JS::UndefinedHandleValue);
 
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  OperationsTestInterface::OverloadedFunction(arg1, arg2);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
-JSBool fcn_voidFunctionLongArg(
+JSBool staticfcn_overloadedFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
-  // Compute the 'this' value.
-  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
-  // 'this' should be an object.
-  JS::RootedObject object(context);
-  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
-    NOTREACHED();
-    return false;
-  }
-  if (!JS_ValueToObject(context, this_value, object.address())) {
-    NOTREACHED();
-    return false;
-  }
-
   JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  const size_t kMinArguments = 1;
-  if (args.length() < kMinArguments) {
-    exception_state.SetSimpleException(
-        script::ExceptionState::kTypeError, "Not enough arguments.");
-    return false;
+  switch(argc) {
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticfcn_overloadedFunction1(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(2): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticfcn_overloadedFunction2(
+                  context, argc, vp);
+      }
+      break;
+    }
   }
-  TypeTraits<int32_t >::ConversionType arg;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VoidFunctionLongArg(arg);
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
-}
-
-JSBool fcn_voidFunctionNoArgs(
-    JSContext* context, uint32_t argc, JS::Value *vp) {
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
   MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
-  // Compute the 'this' value.
-  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
-  // 'this' should be an object.
-  JS::RootedObject object(context);
-  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
-    NOTREACHED();
-    return false;
-  }
-  if (!JS_ValueToObject(context, this_value, object.address())) {
-    NOTREACHED();
-    return false;
-  }
-
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VoidFunctionNoArgs();
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
-}
-
-JSBool fcn_voidFunctionObjectArg(
-    JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
-  // Compute the 'this' value.
-  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
-  // 'this' should be an object.
-  JS::RootedObject object(context);
-  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
-    NOTREACHED();
-    return false;
-  }
-  if (!JS_ValueToObject(context, this_value, object.address())) {
-    NOTREACHED();
-    return false;
-  }
-
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  const size_t kMinArguments = 1;
-  if (args.length() < kMinArguments) {
-    exception_state.SetSimpleException(
-        script::ExceptionState::kTypeError, "Not enough arguments.");
-    return false;
-  }
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VoidFunctionObjectArg(arg);
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
-}
-
-JSBool fcn_voidFunctionStringArg(
-    JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
-  // Compute the 'this' value.
-  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
-  // 'this' should be an object.
-  JS::RootedObject object(context);
-  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
-    NOTREACHED();
-    return false;
-  }
-  if (!JS_ValueToObject(context, this_value, object.address())) {
-    NOTREACHED();
-    return false;
-  }
-
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-  const size_t kMinArguments = 1;
-  if (args.length() < kMinArguments) {
-    exception_state.SetSimpleException(
-        script::ExceptionState::kTypeError, "Not enough arguments.");
-    return false;
-  }
-  TypeTraits<std::string >::ConversionType arg;
-  DCHECK_LT(0, args.length());
-  FromJSValue(context, args.handleAt(0),
-      kNoConversionFlags, &exception_state, &arg);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-  OperationsTestInterface* impl =
-      WrapperPrivate::GetWrappable<OperationsTestInterface>(object);
-  impl->VoidFunctionStringArg(arg);
-  result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
 }
 
 
@@ -813,6 +1444,17 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  {
+      "overloadedFunction",
+      JSOP_WRAPPER(&staticfcn_overloadedFunction),
+      1,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -832,7 +1474,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -852,8 +1495,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "OperationsTestInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "OperationsTestInterface"));
+  const char name[] =
+      "OperationsTestInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -862,8 +1506,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -895,7 +1544,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsOperationsTestInterface::CreateInstance(
+JSObject* MozjsOperationsTestInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -903,8 +1552,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsOperationsTestInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
index 7358b5a..d0e54e1 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsOperationsTestInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsOperationsTestInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
index 5e84fd6..b977879 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.cc
@@ -30,14 +30,20 @@
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -55,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +88,37 @@
 
 namespace {
 
+class MozjsPutForwardsInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsPutForwardsInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsPutForwardsInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsPutForwardsInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsPutForwardsInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "PutForwardsInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +174,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  PutForwardsInterface* impl =
-      WrapperPrivate::GetWrappable<PutForwardsInterface>(object);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ReturnType value =
-      impl->forwarding_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  PutForwardsInterface* impl =
+      wrapper_private->wrappable<PutForwardsInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->forwarding_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_forwardingAttribute(
@@ -152,14 +196,78 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType value;
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  PutForwardsInterface* impl =
+      wrapper_private->wrappable<PutForwardsInterface>().get();
+  { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_impl.
+    scoped_refptr<ArbitraryInterface> forwarded_impl =
+       impl->forwarding_attribute();
+    if (!forwarded_impl) {
+      NOTREACHED();
+      return false;
+    }
+    if (!exception_state.is_exception_set()) {
+  TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  NOTIMPLEMENTED();
-  return !exception_state.IsExceptionSet();
+
+  forwarded_impl->set_arbitrary_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+    return !exception_state.is_exception_set();
+  } // End scope of scoped_refptr<ArbitraryInterface> forwarded_impl.
+}
+
+JSBool staticget_staticForwardingAttribute(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              PutForwardsInterface::static_forwarding_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticset_staticForwardingAttribute(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  { // Begin scope of scoped_refptr<ArbitraryInterface> forwarded_impl.
+    scoped_refptr<ArbitraryInterface> forwarded_impl =
+       PutForwardsInterface::static_forwarding_attribute();
+    if (!forwarded_impl) {
+      NOTREACHED();
+      return false;
+    }
+    if (!exception_state.is_exception_set()) {
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  forwarded_impl->set_arbitrary_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+    return !exception_state.is_exception_set();
+  } // End scope of scoped_refptr<ArbitraryInterface> forwarded_impl.
 }
 
 
@@ -178,9 +286,19 @@
 };
 
 const JSPropertySpec interface_object_properties[] = {
+  {  // Static read/write attribute.
+      "staticForwardingAttribute", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&staticget_staticForwardingAttribute),
+      JSOP_WRAPPER(&staticset_staticForwardingAttribute),
+  },
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -200,7 +318,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -220,8 +339,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "PutForwardsInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "PutForwardsInterface"));
+  const char name[] =
+      "PutForwardsInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -230,8 +350,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -263,7 +388,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsPutForwardsInterface::CreateInstance(
+JSObject* MozjsPutForwardsInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -271,8 +396,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsPutForwardsInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
index eb3d435..06a6435 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsPutForwardsInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsPutForwardsInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
index d968eb9..f07d2b5 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.cc
@@ -24,11 +24,79 @@
 #include "MozjsArbitraryInterface.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/mozjs_callback_interface.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jscntxt.h"
+
 namespace {
 using cobalt::bindings::testing::SingleOperationInterface;
 using cobalt::bindings::testing::MozjsSingleOperationInterface;
 using cobalt::bindings::testing::ArbitraryInterface;
 using cobalt::bindings::testing::MozjsArbitraryInterface;
+
+using cobalt::script::LoggingExceptionState;
+using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::GetCallableForCallbackInterface;
+using cobalt::script::mozjs::ToJSValue;
 }  // namespace
 
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+MozjsSingleOperationInterface::MozjsSingleOperationInterface(
+    JSContext* context,
+    JS::HandleObject implementing_object)
+    : context_(context),
+      implementing_object_(implementing_object) { }
+
+base::optional<int32_t > MozjsSingleOperationInterface::HandleCallback(
+    const scoped_refptr<script::Wrappable>& callback_this,
+    const scoped_refptr<ArbitraryInterface>& value,
+    bool* had_exception) const {
+  JSAutoRequest auto_request(context_);
+  JSAutoCompartment auto_compartment(context_, implementing_object_);
+
+  bool success = false;
+  base::optional<int32_t > cobalt_return_value;
+  // Get callable object.
+  JS::RootedValue callable(context_);
+  if (GetCallableForCallbackInterface(context_, implementing_object_,
+                                      "handleCallback", &callable)) {
+    // Convert the callback_this to a JSValue.
+    JS::RootedValue this_value(context_);
+    ToJSValue(context_, callback_this, &this_value);
+
+    // Convert arguments.
+    const int kNumArguments = 1;
+    JS::Value args[kNumArguments];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, value,
+              auto_array_rooter.handleAt(0));
+
+    // Call the function.
+    JS::RootedValue return_value(context_);
+    JSFunction* function = JS_ValueToFunction(context_, callable);
+    DCHECK(function);
+    success = JS::Call(context_, this_value, function, kNumArguments, args,
+                       return_value.address());
+    DLOG_IF(WARNING, !success) << "Exception in callback.";
+    if (success) {
+      LoggingExceptionState exception_state;
+      FromJSValue(context_, return_value, 0, &exception_state,
+                  &cobalt_return_value);
+      success = !exception_state.is_exception_set();
+    }
+  }
+
+  *had_exception = !success;
+  return cobalt_return_value;
+}
+
+}  // namespace bindings
+}  // namespace testing
+}  // namespace cobalt
 
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
index cd32f68..f2bb3be 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsSingleOperationInterface.h
@@ -26,11 +26,28 @@
 // Headers for other bindings wrapper classes
 #include "cobalt/bindings/testing/single_operation_interface.h"
 
+#include "third_party/mozjs/js/src/jsapi.h"
+
 namespace cobalt {
 namespace bindings {
 namespace testing {
 
-class MozjsSingleOperationInterface { };
+class MozjsSingleOperationInterface : public SingleOperationInterface {
+ public:
+  typedef SingleOperationInterface BaseType;
+
+  MozjsSingleOperationInterface(
+      JSContext* context, JS::HandleObject implementing_object);
+  base::optional<int32_t > HandleCallback(
+      const scoped_refptr<script::Wrappable>& callback_this,
+      const scoped_refptr<ArbitraryInterface>& value,
+      bool* had_exception) const OVERRIDE;
+  JSObject* handle() const { return implementing_object_; }
+
+ private:
+  JSContext* context_;
+  JS::Heap<JSObject*> implementing_object_;
+};
 
 }  // namespace bindings
 }  // namespace testing
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
index aaa8f00..210586c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.cc
@@ -26,22 +26,32 @@
 #include "cobalt/script/global_object_proxy.h"
 #include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_object.h"
+#include "MozjsArbitraryInterface.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
 namespace {
 using cobalt::bindings::testing::StaticPropertiesInterface;
 using cobalt::bindings::testing::MozjsStaticPropertiesInterface;
+using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::MozjsArbitraryInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalObjectProxy;
 using cobalt::script::OpaqueHandle;
@@ -51,6 +61,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +72,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +88,37 @@
 
 namespace {
 
+class MozjsStaticPropertiesInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsStaticPropertiesInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsStaticPropertiesInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsStaticPropertiesInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsStaticPropertiesInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +155,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "StaticPropertiesInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -124,6 +169,288 @@
   return interface_data;
 }
 
+JSBool staticget_staticAttribute(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              StaticPropertiesInterface::static_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticset_staticAttribute(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  TypeTraits<std::string >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  StaticPropertiesInterface::set_static_attribute(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction1(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+
+  StaticPropertiesInterface::StaticFunction();
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction2(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  StaticPropertiesInterface::StaticFunction(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction3(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  const size_t kMinArguments = 1;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<std::string >::ConversionType arg;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  StaticPropertiesInterface::StaticFunction(arg);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction4(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  const size_t kMinArguments = 3;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<int32_t >::ConversionType arg3;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(2, args.length());
+  JS::RootedValue non_optional_value2(
+      context, args[2]);
+  FromJSValue(context,
+              non_optional_value2,
+              kNoConversionFlags,
+              &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction5(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  const size_t kMinArguments = 3;
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+  // Non-optional arguments
+  TypeTraits<int32_t >::ConversionType arg1;
+  TypeTraits<int32_t >::ConversionType arg2;
+  TypeTraits<scoped_refptr<ArbitraryInterface> >::ConversionType arg3;
+
+  DCHECK_LT(0, args.length());
+  JS::RootedValue non_optional_value0(
+      context, args[0]);
+  FromJSValue(context,
+              non_optional_value0,
+              kNoConversionFlags,
+              &exception_state, &arg1);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(1, args.length());
+  JS::RootedValue non_optional_value1(
+      context, args[1]);
+  FromJSValue(context,
+              non_optional_value1,
+              kNoConversionFlags,
+              &exception_state, &arg2);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  DCHECK_LT(2, args.length());
+  JS::RootedValue non_optional_value2(
+      context, args[2]);
+  FromJSValue(context,
+              non_optional_value2,
+              kNoConversionFlags,
+              &exception_state, &arg3);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  StaticPropertiesInterface::StaticFunction(arg1, arg2, arg3);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
+
+JSBool staticfcn_staticFunction(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  switch(argc) {
+    case(0): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      if (true) {
+        return staticfcn_staticFunction1(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(1): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JS::RootedValue arg(context, args[0]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+      if (arg.isNumber()) {
+        return staticfcn_staticFunction2(
+                  context, argc, vp);
+      }
+      if (true) {
+        return staticfcn_staticFunction3(
+                  context, argc, vp);
+      }
+      if (true) {
+        return staticfcn_staticFunction2(
+                  context, argc, vp);
+      }
+      break;
+    }
+    case(3): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+      JS::RootedValue arg(context, args[2]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+      if (arg.isObject() ? wrapper_factory->DoesObjectImplementInterface(
+              JSVAL_TO_OBJECT(arg), base::GetTypeId<ArbitraryInterface>()) :
+              false) {
+        return staticfcn_staticFunction5(
+                  context, argc, vp);
+      }
+      if (true) {
+        return staticfcn_staticFunction4(
+                  context, argc, vp);
+      }
+      break;
+    }
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  MozjsExceptionState exception_state(context);
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
+}
+
 
 const JSPropertySpec prototype_properties[] = {
   JS_PS_END
@@ -134,9 +461,26 @@
 };
 
 const JSPropertySpec interface_object_properties[] = {
+  {  // Static read/write attribute.
+      "staticAttribute", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&staticget_staticAttribute),
+      JSOP_WRAPPER(&staticset_staticAttribute),
+  },
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  {
+      "staticFunction",
+      JSOP_WRAPPER(&staticfcn_staticFunction),
+      0,
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -156,7 +500,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -176,8 +521,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "StaticPropertiesInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "StaticPropertiesInterface"));
+  const char name[] =
+      "StaticPropertiesInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -186,8 +532,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -219,7 +570,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsStaticPropertiesInterface::CreateInstance(
+JSObject* MozjsStaticPropertiesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -227,8 +578,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsStaticPropertiesInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
index 7e7d06a..db46890 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStaticPropertiesInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsStaticPropertiesInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
index 8a5500a..d77b60e 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsStringifierAnonymousOperationInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsStringifierAnonymousOperationInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsStringifierAnonymousOperationInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsStringifierAnonymousOperationInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsStringifierAnonymousOperationInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "StringifierAnonymousOperationInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -125,11 +166,50 @@
 }
 
 
+JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) {
+  MozjsExceptionState exception_state(context);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  StringifierAnonymousOperationInterface* impl =
+      wrapper_private->wrappable<StringifierAnonymousOperationInterface>().get();
+  if (!impl) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Stringifier problem.");
+    NOTREACHED();
+    return false;
+  }
+  std::string stringified = impl->AnonymousStringifier();
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  JS::RootedString rooted_string(context,
+      JS_NewStringCopyN(context, stringified.c_str(), stringified.length()));
+  args.rval().set(JS::StringValue(rooted_string));
+  return true;
+}
+
 const JSPropertySpec prototype_properties[] = {
   JS_PS_END
 };
 
 const JSFunctionSpec prototype_functions[] = {
+  {
+      "toString",
+      JSOP_WRAPPER(&Stringifier),
+      0,
+      JSPROP_PERMANENT,
+      NULL,
+  },
   JS_FS_END
 };
 
@@ -137,6 +217,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -156,7 +240,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -176,8 +261,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "StringifierAnonymousOperationInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "StringifierAnonymousOperationInterface"));
+  const char name[] =
+      "StringifierAnonymousOperationInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -186,8 +272,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -219,7 +310,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsStringifierAnonymousOperationInterface::CreateInstance(
+JSObject* MozjsStringifierAnonymousOperationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -227,8 +318,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsStringifierAnonymousOperationInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
index d2c4c8a..0115c6a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAnonymousOperationInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsStringifierAnonymousOperationInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
index 8d75bef..d652475 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsStringifierAttributeInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsStringifierAttributeInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsStringifierAttributeInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsStringifierAttributeInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsStringifierAttributeInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "StringifierAttributeInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -129,18 +170,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  StringifierAttributeInterface* impl =
-      WrapperPrivate::GetWrappable<StringifierAttributeInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->the_stringifier_attribute();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  StringifierAttributeInterface* impl =
+      wrapper_private->wrappable<StringifierAttributeInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->the_stringifier_attribute(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_theStringifierAttribute(
@@ -148,21 +192,56 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  StringifierAttributeInterface* impl =
+      wrapper_private->wrappable<StringifierAttributeInterface>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  StringifierAttributeInterface* impl =
-      WrapperPrivate::GetWrappable<StringifierAttributeInterface>(object);
+
   impl->set_the_stringifier_attribute(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
+JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) {
+  MozjsExceptionState exception_state(context);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  StringifierAttributeInterface* impl =
+      wrapper_private->wrappable<StringifierAttributeInterface>().get();
+  if (!impl) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Stringifier problem.");
+    NOTREACHED();
+    return false;
+  }
+  std::string stringified = impl->the_stringifier_attribute();
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  JS::RootedString rooted_string(context,
+      JS_NewStringCopyN(context, stringified.c_str(), stringified.length()));
+  args.rval().set(JS::StringValue(rooted_string));
+  return true;
+}
+
 const JSPropertySpec prototype_properties[] = {
   {  // Read/Write property
       "theStringifierAttribute", 0,
@@ -174,6 +253,13 @@
 };
 
 const JSFunctionSpec prototype_functions[] = {
+  {
+      "toString",
+      JSOP_WRAPPER(&Stringifier),
+      0,
+      JSPROP_PERMANENT,
+      NULL,
+  },
   JS_FS_END
 };
 
@@ -181,6 +267,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -200,7 +290,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -220,8 +311,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "StringifierAttributeInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "StringifierAttributeInterface"));
+  const char name[] =
+      "StringifierAttributeInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -230,8 +322,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -263,7 +360,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsStringifierAttributeInterface::CreateInstance(
+JSObject* MozjsStringifierAttributeInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -271,8 +368,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsStringifierAttributeInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
index 8574e32..813ec74 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierAttributeInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsStringifierAttributeInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
index 0f81b4e..30a5d06 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsStringifierOperationInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsStringifierOperationInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsStringifierOperationInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsStringifierOperationInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsStringifierOperationInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "StringifierOperationInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -126,9 +167,7 @@
 
 JSBool fcn_theStringifierOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -141,29 +180,71 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   StringifierOperationInterface* impl =
-      WrapperPrivate::GetWrappable<StringifierOperationInterface>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->TheStringifierOperation();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
+      wrapper_private->wrappable<StringifierOperationInterface>().get();
 
-  if (!exception_state.IsExceptionSet()) {
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->TheStringifierOperation(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     args.rval().set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
+JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) {
+  MozjsExceptionState exception_state(context);
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
+  }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  StringifierOperationInterface* impl =
+      wrapper_private->wrappable<StringifierOperationInterface>().get();
+  if (!impl) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Stringifier problem.");
+    NOTREACHED();
+    return false;
+  }
+  std::string stringified = impl->TheStringifierOperation();
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  JS::RootedString rooted_string(context,
+      JS_NewStringCopyN(context, stringified.c_str(), stringified.length()));
+  args.rval().set(JS::StringValue(rooted_string));
+  return true;
+}
+
 const JSPropertySpec prototype_properties[] = {
   JS_PS_END
 };
 
 const JSFunctionSpec prototype_functions[] = {
   {
+      "toString",
+      JSOP_WRAPPER(&Stringifier),
+      0,
+      JSPROP_PERMANENT,
+      NULL,
+  },
+  {
       "theStringifierOperation",
       JSOP_WRAPPER(&fcn_theStringifierOperation),
       0,
@@ -177,6 +258,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -196,7 +281,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -216,8 +302,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "StringifierOperationInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "StringifierOperationInterface"));
+  const char name[] =
+      "StringifierOperationInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -226,8 +313,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -259,7 +351,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsStringifierOperationInterface::CreateInstance(
+JSObject* MozjsStringifierOperationInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -267,8 +359,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsStringifierOperationInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
index ce7ac6a..135e07a 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsStringifierOperationInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsStringifierOperationInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
index 011ebc7..b7d73d0 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.cc
@@ -28,14 +28,20 @@
 #include "cobalt/script/script_object.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -51,6 +57,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -61,7 +68,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -75,6 +84,37 @@
 
 namespace {
 
+class MozjsTargetInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsTargetInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsTargetInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsTargetInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsTargetInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -111,7 +151,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "TargetInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -126,9 +167,7 @@
 
 JSBool fcn_implementedInterfaceFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -141,24 +180,22 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   TargetInterface* impl =
-      WrapperPrivate::GetWrappable<TargetInterface>(object);
+      wrapper_private->wrappable<TargetInterface>().get();
+
   impl->ImplementedInterfaceFunction();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_partialInterfaceFunction(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -171,17 +208,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   TargetInterface* impl =
-      WrapperPrivate::GetWrappable<TargetInterface>(object);
+      wrapper_private->wrappable<TargetInterface>().get();
+
   impl->PartialInterfaceFunction();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -211,6 +248,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -230,7 +271,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -250,8 +292,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "TargetInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "TargetInterface"));
+  const char name[] =
+      "TargetInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -260,8 +303,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -293,7 +341,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsTargetInterface::CreateInstance(
+JSObject* MozjsTargetInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -301,8 +349,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsTargetInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
index 63f4056..71f1e20 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsTargetInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsTargetInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
index 1aa4ef7..8d181ac 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.cc
@@ -27,17 +27,25 @@
 #include "cobalt/script/opaque_handle.h"
 #include "cobalt/script/script_object.h"
 #include "MozjsArbitraryInterface.h"
+#include "MozjsBaseInterface.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -45,7 +53,9 @@
 using cobalt::bindings::testing::UnionTypesInterface;
 using cobalt::bindings::testing::MozjsUnionTypesInterface;
 using cobalt::bindings::testing::ArbitraryInterface;
+using cobalt::bindings::testing::BaseInterface;
 using cobalt::bindings::testing::MozjsArbitraryInterface;
+using cobalt::bindings::testing::MozjsBaseInterface;
 using cobalt::script::CallbackInterfaceTraits;
 using cobalt::script::GlobalObjectProxy;
 using cobalt::script::OpaqueHandle;
@@ -55,6 +65,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -65,7 +76,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -79,6 +92,37 @@
 
 namespace {
 
+class MozjsUnionTypesInterfaceHandler : public ProxyHandler {
+ public:
+  MozjsUnionTypesInterfaceHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsUnionTypesInterfaceHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsUnionTypesInterfaceHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsUnionTypesInterfaceHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -115,7 +159,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "UnionTypesInterfaceConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -133,18 +178,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
-  TypeTraits<script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t > >::ReturnType value =
-      impl->union_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->union_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_unionProperty(
@@ -152,18 +200,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
   TypeTraits<script::UnionType4<std::string, bool, scoped_refptr<ArbitraryInterface>, int32_t > >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
+
   impl->set_union_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_unionWithNullableMemberProperty(
@@ -171,18 +222,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
-  TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ReturnType value =
-      impl->union_with_nullable_member_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->union_with_nullable_member_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_unionWithNullableMemberProperty(
@@ -190,18 +244,21 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
   TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
+
   impl->set_union_with_nullable_member_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool get_nullableUnionProperty(
@@ -209,18 +266,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
-  TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ReturnType value =
-      impl->nullable_union_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->nullable_union_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_nullableUnionProperty(
@@ -228,18 +288,65 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
   TypeTraits<base::optional<script::UnionType2<double, std::string > > >::ConversionType value;
   FromJSValue(context, vp, (kConversionFlagNullable), &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  UnionTypesInterface* impl =
-      WrapperPrivate::GetWrappable<UnionTypesInterface>(object);
+
   impl->set_nullable_union_property(value);
   result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
+}
 
-  return !exception_state.IsExceptionSet();
+JSBool get_unionBaseProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->union_base_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+JSBool set_unionBaseProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  UnionTypesInterface* impl =
+      wrapper_private->wrappable<UnionTypesInterface>().get();
+  TypeTraits<script::UnionType2<scoped_refptr<BaseInterface>, std::string > >::ConversionType value;
+  FromJSValue(context, vp, kNoConversionFlags, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+
+  impl->set_union_base_property(value);
+  result_value.set(JS::UndefinedHandleValue);
+  return !exception_state.is_exception_set();
 }
 
 
@@ -262,6 +369,12 @@
       JSOP_WRAPPER(&get_nullableUnionProperty),
       JSOP_WRAPPER(&set_nullableUnionProperty),
   },
+  {  // Read/Write property
+      "unionBaseProperty", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&get_unionBaseProperty),
+      JSOP_WRAPPER(&set_unionBaseProperty),
+  },
   JS_PS_END
 };
 
@@ -273,6 +386,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -292,7 +409,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -312,8 +430,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "UnionTypesInterface";
-  name_value.setString(JS_NewStringCopyZ(context, "UnionTypesInterface"));
+  const char name[] =
+      "UnionTypesInterface";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -322,8 +441,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -355,7 +479,7 @@
 }  // namespace
 
 // static
-JSObject* MozjsUnionTypesInterface::CreateInstance(
+JSObject* MozjsUnionTypesInterface::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -363,8 +487,19 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
+
+//static
+const JSClass* MozjsUnionTypesInterface::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
index 1465336..eba6b2f 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsUnionTypesInterface.h
@@ -38,8 +38,9 @@
 
 class MozjsUnionTypesInterface {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
index f0e09c3..b626b88 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.cc
@@ -116,14 +116,20 @@
 #include "cobalt/bindings/testing/window.h"
 
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 
@@ -235,6 +241,7 @@
 
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -245,7 +252,9 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
@@ -259,6 +268,37 @@
 
 namespace {
 
+class MozjsWindowHandler : public ProxyHandler {
+ public:
+  MozjsWindowHandler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+MozjsWindowHandler::named_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+ProxyHandler::IndexedPropertyHooks
+MozjsWindowHandler::indexed_property_hooks = {
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+static base::LazyInstance<MozjsWindowHandler>
+    proxy_handler;
+
+
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
   memset(&interface_data->instance_class_definition, 0,
@@ -295,7 +335,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "WindowConstructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -313,18 +354,21 @@
     JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  Window* impl =
-      WrapperPrivate::GetWrappable<Window>(object);
-  TypeTraits<std::string >::ReturnType value =
-      impl->window_property();
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
-  }
 
-  if (!exception_state.IsExceptionSet()) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  Window* impl =
+      wrapper_private->wrappable<Window>().get();
+
+  if (!exception_state.is_exception_set()) {
+    ToJSValue(context,
+              impl->window_property(),
+              &result_value);
+  }
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool set_windowProperty(
@@ -332,25 +376,26 @@
     JSBool strict, JS::MutableHandleValue vp) {
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
+
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  Window* impl =
+      wrapper_private->wrappable<Window>().get();
   TypeTraits<std::string >::ConversionType value;
   FromJSValue(context, vp, kNoConversionFlags, &exception_state,
               &value);
-  if (exception_state.IsExceptionSet()) {
+  if (exception_state.is_exception_set()) {
     return false;
   }
-  Window* impl =
-      WrapperPrivate::GetWrappable<Window>(object);
+
   impl->set_window_property(value);
   result_value.set(JS::UndefinedHandleValue);
-
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 JSBool fcn_windowOperation(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -363,17 +408,17 @@
     NOTREACHED();
     return false;
   }
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
 
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
   Window* impl =
-      WrapperPrivate::GetWrappable<Window>(object);
+      wrapper_private->wrappable<Window>().get();
+
   impl->WindowOperation();
   result_value.set(JS::UndefinedHandleValue);
-
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 
@@ -402,6 +447,10 @@
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
   JS_PS_END
 };
@@ -421,7 +470,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -441,8 +491,9 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "Window";
-  name_value.setString(JS_NewStringCopyZ(context, "Window"));
+  const char name[] =
+      "Window";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
@@ -451,8 +502,13 @@
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -483,7 +539,7 @@
 
 }  // namespace
 
-JSObject* MozjsWindow::CreateInstance(
+JSObject* MozjsWindow::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject global_object(
@@ -514,9 +570,19 @@
   success = JS_DefineProperties(context, global_object, own_properties);
   DCHECK(success);
 
-  WrapperPrivate::AddPrivateData(global_object, wrappable);
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, global_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
+}
 
-  return global_object;
+//static
+const JSClass* MozjsWindow::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
 }
 
 // static
@@ -559,141 +625,183 @@
   JSContext* context = mozjs_global_object_proxy->context();
 
   JSAutoRequest auto_request(context);
-  MozjsWindow::CreateInstance(
+  MozjsWindow::CreateProxy(
       context, global_interface);
   mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings);
 
   WrapperFactory* wrapper_factory = mozjs_global_object_proxy->wrapper_factory();
   wrapper_factory->RegisterWrappableType(
       AnonymousIndexedGetterInterface::AnonymousIndexedGetterInterfaceWrappableType(),
-      base::Bind(MozjsAnonymousIndexedGetterInterface::CreateInstance));
+      base::Bind(MozjsAnonymousIndexedGetterInterface::CreateProxy),
+      base::Bind(MozjsAnonymousIndexedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       AnonymousNamedGetterInterface::AnonymousNamedGetterInterfaceWrappableType(),
-      base::Bind(MozjsAnonymousNamedGetterInterface::CreateInstance));
+      base::Bind(MozjsAnonymousNamedGetterInterface::CreateProxy),
+      base::Bind(MozjsAnonymousNamedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       AnonymousNamedIndexedGetterInterface::AnonymousNamedIndexedGetterInterfaceWrappableType(),
-      base::Bind(MozjsAnonymousNamedIndexedGetterInterface::CreateInstance));
+      base::Bind(MozjsAnonymousNamedIndexedGetterInterface::CreateProxy),
+      base::Bind(MozjsAnonymousNamedIndexedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ArbitraryInterface::ArbitraryInterfaceWrappableType(),
-      base::Bind(MozjsArbitraryInterface::CreateInstance));
+      base::Bind(MozjsArbitraryInterface::CreateProxy),
+      base::Bind(MozjsArbitraryInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       BaseInterface::BaseInterfaceWrappableType(),
-      base::Bind(MozjsBaseInterface::CreateInstance));
+      base::Bind(MozjsBaseInterface::CreateProxy),
+      base::Bind(MozjsBaseInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       BooleanTypeTestInterface::BooleanTypeTestInterfaceWrappableType(),
-      base::Bind(MozjsBooleanTypeTestInterface::CreateInstance));
+      base::Bind(MozjsBooleanTypeTestInterface::CreateProxy),
+      base::Bind(MozjsBooleanTypeTestInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       CallbackFunctionInterface::CallbackFunctionInterfaceWrappableType(),
-      base::Bind(MozjsCallbackFunctionInterface::CreateInstance));
+      base::Bind(MozjsCallbackFunctionInterface::CreateProxy),
+      base::Bind(MozjsCallbackFunctionInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       CallbackInterfaceInterface::CallbackInterfaceInterfaceWrappableType(),
-      base::Bind(MozjsCallbackInterfaceInterface::CreateInstance));
+      base::Bind(MozjsCallbackInterfaceInterface::CreateProxy),
+      base::Bind(MozjsCallbackInterfaceInterface::PrototypeClass));
 #if defined(ENABLE_CONDITIONAL_INTERFACE)
   wrapper_factory->RegisterWrappableType(
       ConditionalInterface::ConditionalInterfaceWrappableType(),
-      base::Bind(MozjsConditionalInterface::CreateInstance));
+      base::Bind(MozjsConditionalInterface::CreateProxy),
+      base::Bind(MozjsConditionalInterface::PrototypeClass));
 #endif  // defined(ENABLE_CONDITIONAL_INTERFACE)
   wrapper_factory->RegisterWrappableType(
       ConstantsInterface::ConstantsInterfaceWrappableType(),
-      base::Bind(MozjsConstantsInterface::CreateInstance));
+      base::Bind(MozjsConstantsInterface::CreateProxy),
+      base::Bind(MozjsConstantsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ConstructorInterface::ConstructorInterfaceWrappableType(),
-      base::Bind(MozjsConstructorInterface::CreateInstance));
+      base::Bind(MozjsConstructorInterface::CreateProxy),
+      base::Bind(MozjsConstructorInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ConstructorWithArgumentsInterface::ConstructorWithArgumentsInterfaceWrappableType(),
-      base::Bind(MozjsConstructorWithArgumentsInterface::CreateInstance));
+      base::Bind(MozjsConstructorWithArgumentsInterface::CreateProxy),
+      base::Bind(MozjsConstructorWithArgumentsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       DOMStringTestInterface::DOMStringTestInterfaceWrappableType(),
-      base::Bind(MozjsDOMStringTestInterface::CreateInstance));
+      base::Bind(MozjsDOMStringTestInterface::CreateProxy),
+      base::Bind(MozjsDOMStringTestInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       DerivedGetterSetterInterface::DerivedGetterSetterInterfaceWrappableType(),
-      base::Bind(MozjsDerivedGetterSetterInterface::CreateInstance));
+      base::Bind(MozjsDerivedGetterSetterInterface::CreateProxy),
+      base::Bind(MozjsDerivedGetterSetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       DerivedInterface::DerivedInterfaceWrappableType(),
-      base::Bind(MozjsDerivedInterface::CreateInstance));
+      base::Bind(MozjsDerivedInterface::CreateProxy),
+      base::Bind(MozjsDerivedInterface::PrototypeClass));
 #if defined(NO_ENABLE_CONDITIONAL_INTERFACE)
   wrapper_factory->RegisterWrappableType(
       DisabledInterface::DisabledInterfaceWrappableType(),
-      base::Bind(MozjsDisabledInterface::CreateInstance));
+      base::Bind(MozjsDisabledInterface::CreateProxy),
+      base::Bind(MozjsDisabledInterface::PrototypeClass));
 #endif  // defined(NO_ENABLE_CONDITIONAL_INTERFACE)
   wrapper_factory->RegisterWrappableType(
       EnumerationInterface::EnumerationInterfaceWrappableType(),
-      base::Bind(MozjsEnumerationInterface::CreateInstance));
+      base::Bind(MozjsEnumerationInterface::CreateProxy),
+      base::Bind(MozjsEnumerationInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ExceptionObjectInterface::ExceptionObjectInterfaceWrappableType(),
-      base::Bind(MozjsExceptionObjectInterface::CreateInstance));
+      base::Bind(MozjsExceptionObjectInterface::CreateProxy),
+      base::Bind(MozjsExceptionObjectInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ExceptionsInterface::ExceptionsInterfaceWrappableType(),
-      base::Bind(MozjsExceptionsInterface::CreateInstance));
+      base::Bind(MozjsExceptionsInterface::CreateProxy),
+      base::Bind(MozjsExceptionsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ExtendedIDLAttributesInterface::ExtendedIDLAttributesInterfaceWrappableType(),
-      base::Bind(MozjsExtendedIDLAttributesInterface::CreateInstance));
+      base::Bind(MozjsExtendedIDLAttributesInterface::CreateProxy),
+      base::Bind(MozjsExtendedIDLAttributesInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       GetOpaqueRootInterface::GetOpaqueRootInterfaceWrappableType(),
-      base::Bind(MozjsGetOpaqueRootInterface::CreateInstance));
+      base::Bind(MozjsGetOpaqueRootInterface::CreateProxy),
+      base::Bind(MozjsGetOpaqueRootInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       GlobalInterfaceParent::GlobalInterfaceParentWrappableType(),
-      base::Bind(MozjsGlobalInterfaceParent::CreateInstance));
+      base::Bind(MozjsGlobalInterfaceParent::CreateProxy),
+      base::Bind(MozjsGlobalInterfaceParent::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ImplementedInterface::ImplementedInterfaceWrappableType(),
-      base::Bind(MozjsImplementedInterface::CreateInstance));
+      base::Bind(MozjsImplementedInterface::CreateProxy),
+      base::Bind(MozjsImplementedInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       IndexedGetterInterface::IndexedGetterInterfaceWrappableType(),
-      base::Bind(MozjsIndexedGetterInterface::CreateInstance));
+      base::Bind(MozjsIndexedGetterInterface::CreateProxy),
+      base::Bind(MozjsIndexedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       InterfaceWithUnsupportedProperties::InterfaceWithUnsupportedPropertiesWrappableType(),
-      base::Bind(MozjsInterfaceWithUnsupportedProperties::CreateInstance));
+      base::Bind(MozjsInterfaceWithUnsupportedProperties::CreateProxy),
+      base::Bind(MozjsInterfaceWithUnsupportedProperties::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NamedConstructorInterface::NamedConstructorInterfaceWrappableType(),
-      base::Bind(MozjsNamedConstructorInterface::CreateInstance));
+      base::Bind(MozjsNamedConstructorInterface::CreateProxy),
+      base::Bind(MozjsNamedConstructorInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NamedGetterInterface::NamedGetterInterfaceWrappableType(),
-      base::Bind(MozjsNamedGetterInterface::CreateInstance));
+      base::Bind(MozjsNamedGetterInterface::CreateProxy),
+      base::Bind(MozjsNamedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NamedIndexedGetterInterface::NamedIndexedGetterInterfaceWrappableType(),
-      base::Bind(MozjsNamedIndexedGetterInterface::CreateInstance));
+      base::Bind(MozjsNamedIndexedGetterInterface::CreateProxy),
+      base::Bind(MozjsNamedIndexedGetterInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NestedPutForwardsInterface::NestedPutForwardsInterfaceWrappableType(),
-      base::Bind(MozjsNestedPutForwardsInterface::CreateInstance));
+      base::Bind(MozjsNestedPutForwardsInterface::CreateProxy),
+      base::Bind(MozjsNestedPutForwardsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NoConstructorInterface::NoConstructorInterfaceWrappableType(),
-      base::Bind(MozjsNoConstructorInterface::CreateInstance));
+      base::Bind(MozjsNoConstructorInterface::CreateProxy),
+      base::Bind(MozjsNoConstructorInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NoInterfaceObjectInterface::NoInterfaceObjectInterfaceWrappableType(),
-      base::Bind(MozjsNoInterfaceObjectInterface::CreateInstance));
+      base::Bind(MozjsNoInterfaceObjectInterface::CreateProxy),
+      base::Bind(MozjsNoInterfaceObjectInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NullableTypesTestInterface::NullableTypesTestInterfaceWrappableType(),
-      base::Bind(MozjsNullableTypesTestInterface::CreateInstance));
+      base::Bind(MozjsNullableTypesTestInterface::CreateProxy),
+      base::Bind(MozjsNullableTypesTestInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       NumericTypesTestInterface::NumericTypesTestInterfaceWrappableType(),
-      base::Bind(MozjsNumericTypesTestInterface::CreateInstance));
+      base::Bind(MozjsNumericTypesTestInterface::CreateProxy),
+      base::Bind(MozjsNumericTypesTestInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       ObjectTypeBindingsInterface::ObjectTypeBindingsInterfaceWrappableType(),
-      base::Bind(MozjsObjectTypeBindingsInterface::CreateInstance));
+      base::Bind(MozjsObjectTypeBindingsInterface::CreateProxy),
+      base::Bind(MozjsObjectTypeBindingsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       OperationsTestInterface::OperationsTestInterfaceWrappableType(),
-      base::Bind(MozjsOperationsTestInterface::CreateInstance));
+      base::Bind(MozjsOperationsTestInterface::CreateProxy),
+      base::Bind(MozjsOperationsTestInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       PutForwardsInterface::PutForwardsInterfaceWrappableType(),
-      base::Bind(MozjsPutForwardsInterface::CreateInstance));
+      base::Bind(MozjsPutForwardsInterface::CreateProxy),
+      base::Bind(MozjsPutForwardsInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       StaticPropertiesInterface::StaticPropertiesInterfaceWrappableType(),
-      base::Bind(MozjsStaticPropertiesInterface::CreateInstance));
+      base::Bind(MozjsStaticPropertiesInterface::CreateProxy),
+      base::Bind(MozjsStaticPropertiesInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       StringifierAnonymousOperationInterface::StringifierAnonymousOperationInterfaceWrappableType(),
-      base::Bind(MozjsStringifierAnonymousOperationInterface::CreateInstance));
+      base::Bind(MozjsStringifierAnonymousOperationInterface::CreateProxy),
+      base::Bind(MozjsStringifierAnonymousOperationInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       StringifierAttributeInterface::StringifierAttributeInterfaceWrappableType(),
-      base::Bind(MozjsStringifierAttributeInterface::CreateInstance));
+      base::Bind(MozjsStringifierAttributeInterface::CreateProxy),
+      base::Bind(MozjsStringifierAttributeInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       StringifierOperationInterface::StringifierOperationInterfaceWrappableType(),
-      base::Bind(MozjsStringifierOperationInterface::CreateInstance));
+      base::Bind(MozjsStringifierOperationInterface::CreateProxy),
+      base::Bind(MozjsStringifierOperationInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       TargetInterface::TargetInterfaceWrappableType(),
-      base::Bind(MozjsTargetInterface::CreateInstance));
+      base::Bind(MozjsTargetInterface::CreateProxy),
+      base::Bind(MozjsTargetInterface::PrototypeClass));
   wrapper_factory->RegisterWrappableType(
       UnionTypesInterface::UnionTypesInterfaceWrappableType(),
-      base::Bind(MozjsUnionTypesInterface::CreateInstance));
+      base::Bind(MozjsUnionTypesInterface::CreateProxy),
+      base::Bind(MozjsUnionTypesInterface::PrototypeClass));
 
 }
 
diff --git a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
index 3052819..c7e508c 100644
--- a/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
+++ b/src/cobalt/bindings/generated/mozjs/testing/MozjsWindow.h
@@ -39,8 +39,9 @@
 
 class MozjsWindow {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
   static JSObject* GetInterfaceObject(JSContext* context);
 };
diff --git a/src/cobalt/bindings/mozjs/code_generator.py b/src/cobalt/bindings/mozjs/code_generator.py
index 806357d..12ac5fb 100644
--- a/src/cobalt/bindings/mozjs/code_generator.py
+++ b/src/cobalt/bindings/mozjs/code_generator.py
@@ -34,16 +34,19 @@
   """Implementation  of ExpressionGenerator for JavaScriptCore."""
 
   def is_undefined(self, arg):
-    return 'false'
+    return '%s.isUndefined()' % arg
 
   def is_undefined_or_null(self, arg):
-    return 'false'
+    return '%s.isNullOrUndefined()' % arg
 
   def inherits_interface(self, interface_name, arg):
-    return 'false'
+    return ('%s.isObject() ?'
+            ' wrapper_factory->DoesObjectImplementInterface(\n'
+            '              JSVAL_TO_OBJECT(%s), base::GetTypeId<%s>()) :\n'
+            '              false') % (arg, arg, interface_name)
 
   def is_number(self, arg):
-    return 'false'
+    return '%s.isNumber()' % arg
 
 
 class CodeGeneratorMozjs(CodeGeneratorCobalt):
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
index ebbf9f6..421cddb 100644
--- a/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/callback-interface.cc.template
@@ -14,3 +14,96 @@
  # limitations under the License.
  #}
 {% extends "callback-interface-base.cc.template" %}
+
+{% block includes %}
+{{ super() }}
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/mozjs_callback_interface.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jscntxt.h"
+{% endblock includes %}
+
+{% block using_directives %}
+{{ super() }}
+using cobalt::script::LoggingExceptionState;
+using cobalt::script::mozjs::FromJSValue;
+using cobalt::script::mozjs::GetCallableForCallbackInterface;
+using cobalt::script::mozjs::ToJSValue;
+{% endblock using_directives %}
+
+{% block implementation %}
+namespace cobalt {
+{% for component in components %}
+namespace {{component}} {
+{% endfor %}
+
+{{binding_class}}::{{binding_class}}(
+    JSContext* context,
+    JS::HandleObject implementing_object)
+    : context_(context),
+      implementing_object_(implementing_object) { }
+
+{% for operation in operations %}
+{% for overload in operation.overloads %}
+{{overload.type}} {{binding_class}}::{{overload.name}}(
+    const scoped_refptr<script::Wrappable>& callback_this,
+  {% for arg in overload.arguments %}
+    {{arg.arg_type}} {{arg.name}},
+  {% endfor %}
+    bool* had_exception) const {
+  JSAutoRequest auto_request(context_);
+  JSAutoCompartment auto_compartment(context_, implementing_object_);
+
+  bool success = false;
+{% if overload.type != 'void' %}
+  {{overload.type}} cobalt_return_value;
+{% endif %}
+  // Get callable object.
+  JS::RootedValue callable(context_);
+  if (GetCallableForCallbackInterface(context_, implementing_object_,
+                                      "{{overload.idl_name}}", &callable)) {
+    // Convert the callback_this to a JSValue.
+    JS::RootedValue this_value(context_);
+    ToJSValue(context_, callback_this, &this_value);
+
+    // Convert arguments.
+    const int kNumArguments = {{overload.arguments|length}};
+    JS::Value args[kNumArguments];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    {% for arg in overload.arguments %}
+    ToJSValue(context_, {{arg.name}},
+              auto_array_rooter.handleAt({{loop.index0}}));
+    {% endfor %}
+
+    // Call the function.
+    JS::RootedValue return_value(context_);
+    JSFunction* function = JS_ValueToFunction(context_, callable);
+    DCHECK(function);
+    success = JS::Call(context_, this_value, function, kNumArguments, args,
+                       return_value.address());
+    DLOG_IF(WARNING, !success) << "Exception in callback.";
+{% if overload.type != 'void' %}
+    if (success) {
+      LoggingExceptionState exception_state;
+      FromJSValue(context_, return_value, 0, &exception_state,
+                  &cobalt_return_value);
+      success = !exception_state.is_exception_set();
+    }
+{% endif %}
+  }
+
+  *had_exception = !success;
+{% if overload.type != 'void' %}
+  return cobalt_return_value;
+{% endif %}
+}
+{% endfor %}
+{% endfor %}
+
+{% for component in components %}
+}  // namespace {{component}}
+{% endfor %}
+}  // namespace cobalt
+{% endblock implementation %}
diff --git a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
index 8718b2e..1cfeb00 100644
--- a/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
+++ b/src/cobalt/bindings/mozjs/templates/callback-interface.h.template
@@ -15,13 +15,39 @@
  #}
 {% extends "callback-interface-base.h.template" %}
 
+{% block includes %}
+{{ super() }}
+#include "third_party/mozjs/js/src/jsapi.h"
+{% endblock includes %}
+
 {% block implementation %}
 namespace cobalt {
 {% for component in components %}
 namespace {{component}} {
 {% endfor %}
 
-class {{binding_class}} { };
+class {{binding_class}} : public {{impl_class}} {
+ public:
+  typedef {{impl_class}} BaseType;
+
+  {{binding_class}}(
+      JSContext* context, JS::HandleObject implementing_object);
+{% for operation in operations %}
+{% for overload in operation.overloads %}
+  {{overload.type}} {{overload.name}}(
+      const scoped_refptr<script::Wrappable>& callback_this,
+    {% for arg in overload.arguments %}
+      {{arg.arg_type}} {{arg.name}},
+    {% endfor %}
+      bool* had_exception) const OVERRIDE;
+{% endfor %}
+{% endfor %}
+  JSObject* handle() const { return implementing_object_; }
+
+ private:
+  JSContext* context_;
+  JS::Heap<JSObject*> implementing_object_;
+};
 
 {% for component in components %}
 }  // namespace {{component}}
diff --git a/src/cobalt/bindings/mozjs/templates/interface.cc.template b/src/cobalt/bindings/mozjs/templates/interface.cc.template
index d74a60d..ad65ba4 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.cc.template
@@ -13,19 +13,33 @@
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #}
+{% from 'macros.cc.template' import add_extra_arguments %}
 {% from 'macros.cc.template' import call_cobalt_function %}
+{% from 'macros.cc.template' import constructor_implementation with context %}
+{% from 'macros.cc.template' import function_implementation with context %}
+{% from 'macros.cc.template' import get_impl_class_instance %}
+{% from 'macros.cc.template' import nonstatic_function_prologue %}
+{% from 'macros.cc.template' import overload_resolution_implementation with context %}
+{% from 'macros.cc.template' import set_attribute_implementation with context %}
+{% from 'macros.cc.template' import static_function_prologue %}
 {% extends "interface-base.cc.template" %}
 {% block includes %}
 {{ super() }}
 #include "base/lazy_instance.h"
+#include "cobalt/script/mozjs/callback_function_conversion.h"
+#include "cobalt/script/exception_state.h"
 #include "cobalt/script/mozjs/conversion_helpers.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_callback_function.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/proxy_handler.h"
 #include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/property_enumerator.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 #include "third_party/mozjs/js/src/jsfriendapi.h"
 {% endblock includes %}
@@ -33,6 +47,7 @@
 {{ super() }}
 using cobalt::script::CallbackFunction;
 using cobalt::script::CallbackInterfaceTraits;
+using cobalt::script::ExceptionState;
 using cobalt::script::mozjs::FromJSValue;
 using cobalt::script::mozjs::kConversionFlagNullable;
 using cobalt::script::mozjs::kConversionFlagRestricted;
@@ -43,16 +58,243 @@
 using cobalt::script::mozjs::MozjsCallbackFunction;
 using cobalt::script::mozjs::MozjsExceptionState;
 using cobalt::script::mozjs::MozjsGlobalObjectProxy;
-using cobalt::script::mozjs::MozjsObjectHandleHolder;
+using cobalt::script::mozjs::MozjsUserObjectHolder;
+using cobalt::script::mozjs::MozjsPropertyEnumerator;
+using cobalt::script::mozjs::ProxyHandler;
 using cobalt::script::mozjs::ToJSValue;
 using cobalt::script::mozjs::TypeTraits;
 using cobalt::script::mozjs::WrapperPrivate;
 using cobalt::script::mozjs::WrapperFactory;
 using cobalt::script::Wrappable;
 {% endblock using_directives %}
+{% block enumeration_declarations %}
+{% if enumerations|length %}
+// Declare and define these in the same namespace that the other overloads
+// were brought into with the using declaration.
+{% for enumeration in enumerations %}
+void ToJSValue(
+    JSContext* context,
+    {{impl_class}}::{{enumeration.name}} in_enum,
+    JS::MutableHandleValue out_value);
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 {{impl_class}}::{{enumeration.name}}* out_enum);
+{% endfor %}
+{% endif %}
+{% endblock enumeration_declarations %}
 
 {% block implementation %}
 namespace {
+
+{% if named_property_getter %}
+bool IsSupportedNamedProperty(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name) {
+{{ get_impl_class_instance(impl_class) }}
+  return impl->CanQueryNamedProperty(property_name);
+}
+
+void EnumerateSupportedNames(JSContext* context, JS::HandleObject object,
+                             JS::AutoIdVector* properties) {
+{{ get_impl_class_instance(impl_class) }}
+  MozjsPropertyEnumerator enumerator(context, properties);
+  impl->EnumerateNamedProperties(&enumerator);
+}
+
+JSBool GetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+{{ nonstatic_function_prologue(impl_class) }}
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+{{ call_cobalt_function(impl_class, named_property_getter.type,
+                        named_property_getter.name, ["property_name"],
+                        named_property_getter.raises_exception,
+                        named_property_getter.call_with) }}
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+{% if named_property_setter %}
+JSBool SetNamedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+{{ nonstatic_function_prologue(impl_class) }}
+  std::string property_name;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+              &property_name);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<{{named_property_setter.type}} >::ConversionType value;
+  FromJSValue(context, vp, {{named_property_setter.conversion_flags}},
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+{{ call_cobalt_function(impl_class, "void",
+                        named_property_setter.name, ["property_name", "value"],
+                        named_property_setter.raises_exception,
+                        named_property_setter.call_with) }}
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+{% if named_property_deleter %}
+bool DeleteNamedProperty(JSContext* context, JS::HandleObject object,
+                         const std::string& property_name) {
+{{ nonstatic_function_prologue(impl_class) }}
+{{ call_cobalt_function(impl_class, "void",
+                        named_property_deleter.name, ["property_name"],
+                        named_property_deleter.raises_exception,
+                        named_property_deleter.call_with) }}
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+{% if indexed_property_getter %}
+bool IsSupportedIndexProperty(JSContext* context, JS::HandleObject object,
+                              uint32_t index) {
+{{ get_impl_class_instance(impl_class) }}
+  return index < impl->length();
+}
+
+void EnumerateSupportedIndexes(JSContext* context, JS::HandleObject object,
+                               JS::AutoIdVector* properties) {
+{{ get_impl_class_instance(impl_class) }}
+  const uint32_t kNumIndexedProperties = impl->length();
+  for (uint32_t i = 0; i < kNumIndexedProperties; ++i) {
+    properties->append(INT_TO_JSID(i));
+  }
+}
+
+JSBool GetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+{{ nonstatic_function_prologue(impl_class) }}
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+{{ call_cobalt_function(impl_class, indexed_property_getter.type,
+                        indexed_property_getter.name, ["index"],
+                        indexed_property_getter.raises_exception,
+                        indexed_property_getter.call_with) }}
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
+  }
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+{% if indexed_property_setter %}
+JSBool SetIndexedProperty(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+  JS::RootedValue id_value(context);
+  if (!JS_IdToValue(context, id, id_value.address())) {
+    NOTREACHED();
+    return false;
+  }
+{{ nonstatic_function_prologue(impl_class) }}
+  uint32_t index;
+  FromJSValue(context, id_value, kNoConversionFlags, &exception_state, &index);
+  if(exception_state.is_exception_set()) {
+    // The ID should be an integer or a string, so we shouldn't have any
+    // exceptions converting to string.
+    NOTREACHED();
+    return false;
+  }
+  TypeTraits<{{indexed_property_setter.type}} >::ConversionType value;
+  FromJSValue(context, vp, {{indexed_property_setter.conversion_flags}},
+              &exception_state, &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+{{ call_cobalt_function(impl_class, "void",
+                        indexed_property_setter.name, ["index", "value"],
+                        indexed_property_setter.raises_exception,
+                        indexed_property_setter.call_with) }}
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+{% if indexed_property_deleter %}
+bool DeleteIndexedProperty(
+    JSContext* context, JS::HandleObject object, uint32_t index) {
+{{ nonstatic_function_prologue(impl_class) }}
+{{ call_cobalt_function(impl_class, "void",
+                        indexed_property_deleter.name, ["index"],
+                        indexed_property_deleter.raises_exception,
+                        indexed_property_deleter.call_with) }}
+  return !exception_state.is_exception_set();
+}
+
+{% endif %}
+class {{binding_class}}Handler : public ProxyHandler {
+ public:
+  {{binding_class}}Handler()
+      : ProxyHandler(indexed_property_hooks, named_property_hooks) {}
+
+ private:
+  static NamedPropertyHooks named_property_hooks;
+  static IndexedPropertyHooks indexed_property_hooks;
+};
+
+ProxyHandler::NamedPropertyHooks
+{{binding_class}}Handler::named_property_hooks = {
+  {{ "IsSupportedNamedProperty" if named_property_getter else "NULL" }},
+  {{ "EnumerateSupportedNames" if named_property_getter else "NULL" }},
+  {{ "GetNamedProperty" if named_property_getter else "NULL" }},
+  {{ "SetNamedProperty" if named_property_setter else "NULL" }},
+  {{ "DeleteNamedProperty" if named_property_deleter else "NULL" }},
+};
+ProxyHandler::IndexedPropertyHooks
+{{binding_class}}Handler::indexed_property_hooks = {
+  {{ "IsSupportedIndexProperty" if indexed_property_getter else "NULL" }},
+  {{ "EnumerateSupportedIndexes" if indexed_property_getter else "NULL" }},
+  {{ "GetIndexedProperty" if indexed_property_getter else "NULL" }},
+  {{ "SetIndexedProperty" if indexed_property_setter else "NULL" }},
+  {{ "DeleteIndexedProperty" if indexed_property_deleter else "NULL" }},
+};
+
+static base::LazyInstance<{{binding_class}}Handler>
+    proxy_handler;
+
+{% if constructor %}
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp);
+{% endif %}
 {% for constant in constants %}
 JSBool get_{{constant.idl_name}}(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
@@ -67,17 +309,14 @@
 {% endif %}
   MozjsExceptionState exception_state(context);
   JS::RootedValue result_value(context);
-  ToJSValue(context, {{constant.value}}, &exception_state, &result_value);
-  if (!exception_state.IsExceptionSet()) {
-     vp.set(result_value);
+  ToJSValue(context, {{constant.value}}, &result_value);
+  if (!exception_state.is_exception_set()) {
+    vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 {% endfor %}
-{% if constructor %}
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args);
-{% endif %}
 
 InterfaceData* CreateCachedInterfaceData() {
   InterfaceData* interface_data = new InterfaceData();
@@ -89,7 +328,8 @@
          sizeof(interface_data->interface_object_class_definition));
 
   JSClass* instance_class = &interface_data->instance_class_definition;
-  const int kGlobalFlags = {{"JSCLASS_GLOBAL_FLAGS" if is_global_interface else 0 }};
+  const int kGlobalFlags = {{
+      "JSCLASS_GLOBAL_FLAGS" if is_global_interface else 0 }};
   instance_class->name = "{{interface_name}}";
   instance_class->flags = kGlobalFlags | JSCLASS_HAS_PRIVATE;
   instance_class->addProperty = JS_PropertyStub;
@@ -115,7 +355,8 @@
   prototype_class->resolve = JS_ResolveStub;
   prototype_class->convert = JS_ConvertStub;
 
-  JSClass* interface_object_class = &interface_data->interface_object_class_definition;
+  JSClass* interface_object_class =
+      &interface_data->interface_object_class_definition;
   interface_object_class->name = "{{interface_name}}Constructor";
   interface_object_class->flags = 0;
   interface_object_class->addProperty = JS_PropertyStub;
@@ -131,7 +372,7 @@
   return interface_data;
 }
 
-{% for attribute in attributes %}
+{% for attribute in attributes + static_attributes %}
 {% if attribute.conditional %}
 #if defined({{attribute.conditional}})
 {% endif %}
@@ -146,57 +387,78 @@
 }
 
 {% else %}
+{% if attribute.is_static %}
+JSBool staticget_{{attribute.idl_name}}(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JS::MutableHandleValue vp) {
+{{ static_function_prologue() -}}
+{% else %}
 JSBool get_{{attribute.idl_name}}(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JS::MutableHandleValue vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
+{{ nonstatic_function_prologue(impl_class) }}
+{% endif %}
 {{ call_cobalt_function(impl_class, attribute.type,
                         attribute.getter_function_name, [],
-                        attribute.raises_exception, attribute.call_with) }}
-  if (!exception_state.IsExceptionSet()) {
+                        attribute.raises_exception, attribute.call_with,
+                        attribute.is_static) }}
+  if (!exception_state.is_exception_set()) {
     vp.set(result_value);
   }
-  return !exception_state.IsExceptionSet();
+  return !exception_state.is_exception_set();
 }
 
 {% if attribute.has_setter %}
+{% if attribute.is_static %}
+JSBool staticset_{{attribute.idl_name}}(
+    JSContext* context, JS::HandleObject object, JS::HandleId id,
+    JSBool strict, JS::MutableHandleValue vp) {
+{{ static_function_prologue() }}
+{% else %}
 JSBool set_{{attribute.idl_name}}(
     JSContext* context, JS::HandleObject object, JS::HandleId id,
     JSBool strict, JS::MutableHandleValue vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
-  TypeTraits<{{attribute.type}} >::ConversionType value;
-  FromJSValue(context, vp, {{attribute.conversion_flags}}, &exception_state,
-              &value);
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-{% if attribute.put_forwards %}
-  NOTIMPLEMENTED();
-{% else %}
-{{ call_cobalt_function(impl_class, "void", attribute.setter_function_name,
-                        ["value"], attribute.raises_exception, attribute.call_with) }}
-{% endif %}
-  return !exception_state.IsExceptionSet();
+{{ nonstatic_function_prologue(impl_class)}}
+{% endif %} {#- attribute.is_static #}
+{{ set_attribute_implementation(attribute, impl_class) -}}
 }
 
-{% endif %}
+{% endif %} {#- attribute.has_setter #}
 {% endif %}
 {% if attribute.conditional %}
 #endif  // {{attribute.conditional}}
-{% endif %}
+{% endif %} {#- attribute.is_constructor_attribute #}
 {% endfor %}
-
-{%- for operation in operations %}
+{%- for operation in operations + static_operations %}
 {% if operation.conditional %}
 #if defined({{operation.conditional}})
 {% endif %}
-JSBool fcn_{{operation.idl_name}}(
+{% set boundFunctionPrefix = "staticfcn_" if operation.is_static else "fcn_" %}
+{% for overload in operation.overloads if operation.overloads|length > 1 %}
+JSBool {{boundFunctionPrefix}}{{operation.idl_name}}{{overload.overload_index}}(
     JSContext* context, uint32_t argc, JS::Value *vp) {
-  MozjsExceptionState exception_state(context);
-  JS::RootedValue result_value(context);
+{{ function_implementation(overload) -}}
+}
 
+{% endfor %}
+JSBool {{boundFunctionPrefix}}{{operation.idl_name}}(
+    JSContext* context, uint32_t argc, JS::Value *vp) {
+{% if operation.overloads|length == 1 %}
+{{ function_implementation(operation.overloads[0]) -}}
+{% else %}
+{{ overload_resolution_implementation(
+      operation, boundFunctionPrefix + operation.idl_name) }}
+{% endif %}
+}
+
+{% if operation.conditional %}
+#endif  // {{operation.conditional}}
+{% endif %}
+{% endfor %}
+
+{% if stringifier %}
+JSBool Stringifier(JSContext* context, unsigned argc, JS::Value *vp) {
+  MozjsExceptionState exception_state(context);
   // Compute the 'this' value.
   JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
   // 'this' should be an object.
@@ -209,51 +471,25 @@
     NOTREACHED();
     return false;
   }
-
-  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
-{# TODO: Overload resolution. Just use first overload for now. #}
-{% set overload = operation.overloads[0] %}
-{# TODO: Optional and variadic arguments. #}
-{% if overload.arguments|selectattr('is_optional')|selectattr('is_variadic')|list|length == 0 %}
-{% if overload.arguments|length > 0 %}
-  const size_t kMinArguments = {{overload.arguments|length}};
-  if (args.length() < kMinArguments) {
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  {{impl_class}}* impl =
+      wrapper_private->wrappable<{{impl_class}}>().get();
+  if (!impl) {
     exception_state.SetSimpleException(
-        script::ExceptionState::kTypeError, "Not enough arguments.");
+        script::ExceptionState::kTypeError, "Stringifier problem.");
+    NOTREACHED();
     return false;
   }
-{% endif %}
-{% for argument in overload.arguments %}
-  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
-  DCHECK_LT({{loop.index0}}, args.length());
-  FromJSValue(context, args.handleAt({{loop.index0}}),
-      {{argument.conversion_flags}}, &exception_state, &{{argument.name}});
-  if (exception_state.IsExceptionSet()) {
-    return false;
-  }
-{% endfor %}
-{% set arguments = overload.arguments|map(attribute="name")|list %}
-{{ call_cobalt_function(impl_class, overload.type,
-                        overload.name, arguments,
-                        overload.raises_exception,
-                        overload.call_with) }}
-{% if operation.type != 'void' %}
-  if (!exception_state.IsExceptionSet()) {
-    args.rval().set(result_value);
-  }
-{% endif %}
-  return !exception_state.IsExceptionSet();
-{% else %}
-  NOTIMPLEMENTED();
-  return false;
-{% endif %}
+  std::string stringified = impl->{{stringifier.name}}();
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  JS::RootedString rooted_string(context,
+      JS_NewStringCopyN(context, stringified.c_str(), stringified.length()));
+  args.rval().set(JS::StringValue(rooted_string));
+  return true;
 }
 
-{% if operation.conditional %}
-#endif  // {{operation.conditional}}
 {% endif %}
-{% endfor %}
-
 const JSPropertySpec prototype_properties[] = {
 {% for constant in constants %}
   {
@@ -290,6 +526,15 @@
 };
 
 const JSFunctionSpec prototype_functions[] = {
+{% if stringifier %}
+  {
+      "toString",
+      JSOP_WRAPPER(&Stringifier),
+      0,
+      JSPROP_PERMANENT,
+      NULL,
+  },
+{% endif %}
 {% for operation in operations %}
 {% if operation.conditional %}
 #if defined({{operation.conditional}})
@@ -317,9 +562,51 @@
       JSOP_NULLWRAPPER,
   },
 {% endfor %}
+{% for attribute in static_attributes %}
+{% if attribute.conditional %}
+#if defined({{attribute.conditional}})
+{% endif %}
+{% if attribute.has_setter %}
+  {  // Static read/write attribute.
+      "{{attribute.idl_name}}", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE,
+      JSOP_WRAPPER(&staticget_{{attribute.idl_name}}),
+      JSOP_WRAPPER(&staticset_{{attribute.idl_name}}),
+  },
+{% else %}
+  {  // Static readonly attribute.
+      "{{attribute.idl_name}}", 0,
+      JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_READONLY,
+      JSOP_WRAPPER(&staticget_{{attribute.idl_name}}),
+      JSOP_NULLWRAPPER,
+  },
+{% endif %}
+{% if attribute.conditional %}
+#endif  // {{attribute.conditional}}
+{% endif %}
+{% endfor %}
   JS_PS_END
 };
 
+const JSFunctionSpec interface_object_functions[] = {
+{% for operation in static_operations %}
+{% if operation.conditional %}
+#if defined({{operation.conditional}})
+{% endif %}
+  {
+      "{{ operation.idl_name }}",
+      JSOP_WRAPPER(&staticfcn_{{operation.idl_name}}),
+      {{ operation.length }},
+      JSPROP_ENUMERATE,
+      NULL,
+  },
+{% if operation.conditional %}
+#endif  // {{operation.conditional}}
+{% endif %}
+{% endfor %}
+  JS_FS_END
+};
+
 const JSPropertySpec own_properties[] = {
 {% for attribute in attributes if attribute.is_constructor_attribute %}
 {% if attribute.conditional %}
@@ -358,7 +645,8 @@
 
   // Create the Prototype object.
   interface_data->prototype = JS_NewObjectWithGivenProto(
-      context, &interface_data->prototype_class_definition, parent_prototype, NULL);
+      context, &interface_data->prototype_class_definition, parent_prototype,
+      NULL);
   bool success = JS_DefineProperties(
       context, interface_data->prototype, prototype_properties);
   DCHECK(success);
@@ -379,18 +667,36 @@
   JS::RootedObject rooted_interface_object(
       context, interface_data->interface_object);
   JS::RootedValue name_value(context);
-  const char name[] = "{{ named_constructor if named_constructor else interface.name }}";
-  name_value.setString(JS_NewStringCopyZ(context, "{{interface.name}}"));
+  const char name[] =
+      "{{ named_constructor if named_constructor else interface.name }}";
+  name_value.setString(JS_NewStringCopyZ(context, name));
   success =
       JS_DefineProperty(context, rooted_interface_object, "name", name_value,
                         JS_PropertyStub, JS_StrictPropertyStub,
                         JSPROP_READONLY);
   DCHECK(success);
+{% if constructor %}
+
+  // Add the InterfaceObject.length property. It is set to the length of the
+  // shortest argument list of all overload constructors.
+  JS::RootedValue length_value(context);
+  length_value.setInt32({{constructor.length}});
+  success =
+      JS_DefineProperty(context, rooted_interface_object, "length",
+                        length_value, JS_PropertyStub, JS_StrictPropertyStub,
+                        JSPROP_READONLY);
+  DCHECK(success);
+{% endif %}
 
   // Define interface object properties (including constants).
   success = JS_DefineProperties(context, rooted_interface_object,
-                                         interface_object_properties);
+                                interface_object_properties);
   DCHECK(success);
+  // Define interface object functions (static).
+  success = JS_DefineFunctions(context, rooted_interface_object,
+                               interface_object_functions);
+  DCHECK(success);
+
 
   // Set the Prototype.constructor and Constructor.prototype properties.
   DCHECK(interface_data->interface_object);
@@ -423,7 +729,7 @@
 }  // namespace
 
 {% if is_global_interface %}
-JSObject* {{binding_class}}::CreateInstance(
+JSObject* {{binding_class}}::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject global_object(
@@ -454,14 +760,16 @@
   success = JS_DefineProperties(context, global_object, own_properties);
   DCHECK(success);
 
-  WrapperPrivate::AddPrivateData(global_object, wrappable);
-
-  return global_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, global_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
 }
 
 {% else %}
 // static
-JSObject* {{binding_class}}::CreateInstance(
+JSObject* {{binding_class}}::CreateProxy(
     JSContext* context, const scoped_refptr<Wrappable>& wrappable) {
   InterfaceData* interface_data = GetInterfaceData(context);
   JS::RootedObject prototype(context, GetPrototype(context));
@@ -469,11 +777,22 @@
   JS::RootedObject new_object(context, JS_NewObjectWithGivenProto(
       context, &interface_data->instance_class_definition, prototype, NULL));
   DCHECK(new_object);
-  WrapperPrivate::AddPrivateData(new_object, wrappable);
-  return new_object;
+  JS::RootedObject proxy(context,
+      ProxyHandler::NewProxy(context, new_object, prototype, NULL,
+                             proxy_handler.Pointer()));
+  WrapperPrivate::AddPrivateData(proxy, wrappable);
+  return proxy;
 }
 
 {% endif %}
+//static
+const JSClass* {{binding_class}}::PrototypeClass(
+      JSContext* context) {
+  JS::RootedObject prototype(context, GetPrototype(context));
+  JSClass* proto_class = JS_GetClass(*prototype.address());
+  return proto_class;
+}
+
 // static
 JSObject* {{binding_class}}::GetPrototype(JSContext* context) {
   InterfaceData* interface_data = GetInterfaceData(context);
@@ -496,14 +815,23 @@
   return interface_data->interface_object;
 }
 
-{% endif %}
+{% endif %} {#- has_interface_object #}
 
 namespace {
 {% if constructor %}
-JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* args) {
-  // TODO: Implement support for constructors.
-  NOTIMPLEMENTED();
-  return true;
+{% for overload in constructor.overloads if constructor.overloads|length > 1 %}
+JSBool Constructor{{overload.overload_index}}(
+    JSContext* context, unsigned int argc, JS::Value* vp) {
+{{ constructor_implementation(overload) -}}
+}
+
+{% endfor %}
+JSBool Constructor(JSContext* context, unsigned int argc, JS::Value* vp) {
+{% if constructor.overloads|length == 1 %}
+{{ constructor_implementation(constructor.overloads[0]) -}}
+{% else %}
+{{ overload_resolution_implementation(constructor, "Constructor")}}
+{% endif %}
 }
 {% endif %}
 }  // namespace
@@ -515,7 +843,7 @@
   JSContext* context = mozjs_global_object_proxy->context();
 
   JSAutoRequest auto_request(context);
-  {{binding_class}}::CreateInstance(
+  {{binding_class}}::CreateProxy(
       context, global_interface);
   mozjs_global_object_proxy->SetEnvironmentSettings(environment_settings);
 
@@ -529,7 +857,8 @@
   {% if interface.name != impl_class %}
   wrapper_factory->RegisterWrappableType(
       {{interface.name}}::{{interface.name}}WrappableType(),
-      base::Bind(Mozjs{{interface.name}}::CreateInstance));
+      base::Bind(Mozjs{{interface.name}}::CreateProxy),
+      base::Bind(Mozjs{{interface.name}}::PrototypeClass));
   {% endif %}
 {% if interface.conditional %}
 #endif  // defined({{interface.conditional}})
@@ -537,3 +866,48 @@
 {% endfor %}
 
 {% endblock create_global_object_impl %}
+
+{%  block enumeration_definitions %}
+{% for enumeration in enumerations %}
+
+inline void ToJSValue(
+    JSContext* context,
+    {{impl_class}}::{{enumeration.name}} in_enum,
+    JS::MutableHandleValue out_value) {
+
+  switch (in_enum) {
+{% for value, idl_value in enumeration.value_pairs %}
+    case {{impl_class}}::{{value}}:
+      ToJSValue(context, std::string("{{idl_value}}"), out_value);
+      return;
+{% endfor %}
+  }
+}
+
+
+inline void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 {{impl_class}}::{{enumeration.name}}* out_enum) {
+  DCHECK_EQ(0, conversion_flags) << "Unexpected conversion flags.";
+  // JSValue -> IDL enum algorithm described here:
+  // http://heycam.github.io/webidl/#es-enumeration
+  // 1. Let S be the result of calling ToString(V).
+  JS::RootedString rooted_string(context, JS_ValueToString(context, value));
+
+  JSBool match = JS_FALSE;
+// 3. Return the enumeration value of type E that is equal to S.
+{% for value, idl_value in enumeration.value_pairs %}
+  {{-" else " if not loop.first}}if (JS_StringEqualsAscii(
+      context, rooted_string, "{{idl_value}}", &match)
+      && match) {
+    *out_enum = {{impl_class}}::{{value}};
+  }{% endfor %} else {
+    // 2. If S is not one of E's enumeration values, then throw a TypeError.
+    exception_state->
+        SetSimpleException(ExceptionState::kTypeError,
+                           "Cannot convert JavaScript value to Enum.");
+    return;
+  }
+}
+{% endfor %}
+{% endblock enumeration_definitions %}
diff --git a/src/cobalt/bindings/mozjs/templates/interface.h.template b/src/cobalt/bindings/mozjs/templates/interface.h.template
index 9c30315..f7ca8b6 100644
--- a/src/cobalt/bindings/mozjs/templates/interface.h.template
+++ b/src/cobalt/bindings/mozjs/templates/interface.h.template
@@ -21,8 +21,9 @@
 {% block implementation %}
 class {{binding_class}} {
  public:
-  static JSObject* CreateInstance(JSContext* context,
+  static JSObject* CreateProxy(JSContext* context,
       const scoped_refptr<script::Wrappable>& wrappable);
+  static const JSClass* PrototypeClass(JSContext* context);
   static JSObject* GetPrototype(JSContext* context);
 {% if has_interface_object %}
   static JSObject* GetInterfaceObject(JSContext* context);
diff --git a/src/cobalt/bindings/mozjs/templates/macros.cc.template b/src/cobalt/bindings/mozjs/templates/macros.cc.template
index bc3174b..36770e2 100644
--- a/src/cobalt/bindings/mozjs/templates/macros.cc.template
+++ b/src/cobalt/bindings/mozjs/templates/macros.cc.template
@@ -14,31 +14,375 @@
  # limitations under the License.
  #}
 
-{% macro call_nonvoid_function(return_type, function_name, arguments) %}
-  TypeTraits<{{return_type}} >::ReturnType value =
-      impl->{{function_name}}({{arguments|join(", ")}});
-  if (!exception_state.IsExceptionSet()) {
-    ToJSValue(context, value, &exception_state, &result_value);
+{#
+ # Function body for operation bindings.
+ # Parameters:
+ #     operation: The operation context object
+ #}
+{% macro function_implementation(operation) %}
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+{% if operation.is_static %}
+{{ static_function_prologue() }}
+{% else %}
+  // Compute the 'this' value.
+  JS::RootedValue this_value(context, JS_ComputeThis(context, vp));
+  // 'this' should be an object.
+  JS::RootedObject object(context);
+  if (JS_TypeOfValue(context, this_value) != JSTYPE_OBJECT) {
+    NOTREACHED();
+    return false;
   }
+  if (!JS_ValueToObject(context, this_value, object.address())) {
+    NOTREACHED();
+    return false;
+  }
+{{ nonstatic_function_prologue(impl_class) }}
+{% endif %}
+{% call(arguments_list) extract_arguments(operation) %}
+{{ call_cobalt_function(impl_class, operation.type, operation.name,
+                         arguments_list, operation.raises_exception,
+                         operation.call_with, operation.is_static) }}
+{% if operation.type != 'void' %}
+  if (!exception_state.is_exception_set()) {
+    args.rval().set(result_value);
+  }
+{% endif %}
+  return !exception_state.is_exception_set();
+{%- endcall %}
 {%- endmacro %}
 
-{% macro call_void_function(function_name, arguments) %}
-  impl->{{function_name}}({{arguments|join(", ")}});
-  result_value.set(JS::UndefinedHandleValue);
+{#
+ # Function body for setting an attribute value.
+ # Parameters:
+ #     attribute: The attribute context object.
+ #     impl_class: Cobalt class name of the Cobalt implementation of the
+ #         interface on which the attribute is a member.
+ #     cobalt_impl_prefix: Variable name prefix of a pointer to a Cobalt
+ #         implementation of the interface on which the attribute is a member.
+ #}
+{% macro set_attribute_implementation(attribute, impl_class,
+                                      cobalt_impl_prefix="") %}
+{% if attribute.put_forwards %}
+  { // Begin scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl.
+    {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl =
+{% if not attribute.is_static %}
+       {{cobalt_impl_prefix}}impl->{{attribute.getter_function_name}}();
+{% else %}
+       {{impl_class}}::{{attribute.getter_function_name}}();
+{% endif %}
+    if (!forwarded_{{cobalt_impl_prefix}}impl) {
+      NOTREACHED();
+      return false;
+    }
+    if (!exception_state.is_exception_set()) {
+{{ set_attribute_implementation(attribute.put_forwards, attribute.type,
+     "forwarded_" + cobalt_impl_prefix) -}}
+    }
+    return !exception_state.is_exception_set();
+  } // End scope of {{attribute.type}} forwarded_{{cobalt_impl_prefix}}impl.
+{% else %}
+  TypeTraits<{{attribute.type}} >::ConversionType value;
+  FromJSValue(context, vp, {{attribute.conversion_flags}}, &exception_state,
+              &value);
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+{{ call_cobalt_function(impl_class, "void",
+                        attribute.setter_function_name,
+                        ["value"], attribute.raises_exception,
+                        attribute.call_with, attribute.is_static,
+                        cobalt_impl_prefix) }}
+  return !exception_state.is_exception_set();
+{% endif %} {#- attribute.put_forwards #}
 {%- endmacro %}
 
-{% macro call_cobalt_function(impl_class, cobalt_type, function_name, arguments, raises_exception, call_with) %}
+{#
+ # Extract and marshal arguments that will be passed to a function-like call.
+ # Parameters:
+ #     operation: An IdlOperation object
+ # Passed to caller:
+ #     A string that can be used as the parameters for a function call. It will
+ #     be either empty, or a comma-separated list of variable names.
+ #}
+{% macro extract_arguments(operation) %}
+{% set non_optional_arguments = operation.non_optional_arguments %}
+{% set optional_arguments = operation.optional_arguments %}
+{% set num_default_arguments = operation.num_default_arguments %}
+{% set variadic_argument = operation.variadic_argument %}
+{% set has_non_default_optional_arguments =
+          operation.has_non_default_optional_arguments %}
+
+{%- if non_optional_arguments|length > 0 %}
+  const size_t kMinArguments = {{non_optional_arguments|length}};
+  if (args.length() < kMinArguments) {
+    exception_state.SetSimpleException(
+        script::ExceptionState::kTypeError, "Not enough arguments.");
+    return false;
+  }
+{% endif -%}
+
+{# Declare variables for all arguments #}
+{% for argument in non_optional_arguments %}
+{% if loop.first %}
+  // Non-optional arguments
+{% endif %}
+  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
+{% endfor %}
+{% for argument in optional_arguments if argument.default_value %}
+{% if loop.first %}
+  // Optional arguments with default values
+{% endif %}
+  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}} =
+      {{argument.default_value}};
+{% endfor %}
+{% for argument in optional_arguments if not argument.default_value %}
+{% if loop.first %}
+  // Optional arguments
+{% endif %}
+  TypeTraits<{{argument.type}} >::ConversionType {{argument.name}};
+{% endfor %}
+{% if variadic_argument %}
+  // Variadic argument
+  TypeTraits<{{variadic_argument.type}} >::ConversionType {{
+      variadic_argument.name}};
+{% endif -%}
+
+{% for argument in non_optional_arguments %}
+
+  DCHECK_LT({{loop.index0}}, args.length());
+  JS::RootedValue non_optional_value{{loop.index0}}(
+      context, args[{{loop.index0}}]);
+  FromJSValue(context,
+              non_optional_value{{loop.index0}},
+              {{argument.conversion_flags}},
+              &exception_state, &{{argument.name}});
+  if (exception_state.is_exception_set()) {
+    return false;
+  }
+{% endfor -%}
+{% for argument in optional_arguments %}
+{% if loop.first %}
+  size_t num_set_arguments = {{
+      non_optional_arguments|length + num_default_arguments}};
+{% endif %}
+  if (args.length() > {{loop.index0 + non_optional_arguments|length}}) {
+    JS::RootedValue optional_value{{loop.index0}}(
+        context, args[{{loop.index0 + non_optional_arguments|length}}]);
+    FromJSValue(context,
+                optional_value{{loop.index0}},
+                {{argument.conversion_flags}},
+                &exception_state,
+                &{{argument.name}});
+    if (exception_state.is_exception_set()) {
+      return false;
+    }
+{% if not argument.default_value %}
+    ++num_set_arguments;
+{% endif %}
+  }
+{% endfor %}
+{% if variadic_argument %}
+
+  // Get variadic arguments.
+{% if optional_arguments|length %}
+  const size_t kLastOptionalArgIndex = {{
+      non_optional_arguments|length + optional_arguments|length}};
+  if (num_set_arguments == kLastOptionalArgIndex) {
+    // If the last optional argument has been set, we will call the overload
+    // that takes the variadic argument, possibly with an empty vector in the
+    // case that there are no more arguments left.
+    ++num_set_arguments;
+  }
+{% endif %}
+  const size_t kFirstVariadicArgIndex = {{operation.arguments|length - 1}};
+  if (args.length() > kFirstVariadicArgIndex) {
+    {{variadic_argument.name}}.resize(args.length() - kFirstVariadicArgIndex);
+    for (int i = 0; i + kFirstVariadicArgIndex < args.length(); ++i) {
+      JS::RootedValue variadic_argument_value{{i}}(
+          context, args[i + kFirstVariadicArgIndex]);
+      FromJSValue(context,
+                  variadic_argument_value{{i}},
+                  {{variadic_argument.conversion_flags}},
+                  &exception_state,
+                  &{{variadic_argument.name}}[i]);
+      if (exception_state.is_exception_set()) {
+        return false;
+      }
+    }
+  }
+{% endif -%}
+
+{# Call the implementation function, based on the number of set arguments. #}
+{% if has_non_default_optional_arguments %}
+  switch (num_set_arguments) {
+{% for num_arguments in range(
+    non_optional_arguments|length + num_default_arguments,
+    operation.arguments|length + 1) %}
+{# If no variadic arguments have been set, we still call the function with
+   signature that has the variadic argument and pass an empty vector. There is
+   no such function signature that takes the optional parameter immediately
+   preceeding the variadic argument but does not take the variadic arguments. #}
+{% if loop.last or not operation.arguments[num_arguments].is_variadic %}
+{% set function_arguments =
+      operation.arguments[0:num_arguments]|map(attribute='name')|list %}
+    case {{num_arguments}}:
+      {
+        {{- caller(function_arguments)|indent(8, false) }}
+      }
+      break;
+{% endif %}
+{% endfor %}
+    default:
+      NOTREACHED();
+      return false;
+  }
+{% else %} {#- has_non_default_optional_arguments #}
+{% set function_arguments = operation.arguments|map(attribute='name')|list %}
+  {# whitespace control block #}
+  {{-caller(function_arguments)}}
+{% endif %}
+{% endmacro %}
+
+{#
+ # Append extra arguments that should be passed to a cobalt function.
+ # Specifically, this will prepend parameters specified on IDLs using the
+ # [CallWith=] extended attribute.
+ # Parameters:
+ #     arguments_list: A list of C++ expressions that represent a sequence of
+ #         arguments that will be passed to a function.
+ #     context: An IDL object that may have the extended attribute that
+ #         we are interested in.
+ # Passed to caller:
+ #     arguments_list, possibly with extra arguments prepended and appended.
+ #}
+{% macro add_extra_arguments(arguments_list, raises_exception, call_with) %}
 {% if call_with %}
   MozjsGlobalObjectProxy* global_object_proxy =
       static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+{% do arguments_list.insert(0,
+                            'global_object_proxy->Get%s()'|format(call_with)) %}
 {% endif %}
-  {{impl_class}}* impl =
-      WrapperPrivate::GetWrappable<{{impl_class}}>(object);
-{% do arguments.append("&exception_state") if raises_exception %}
-{% do arguments.append("global_object_proxy->Get%s()"|format(call_with)) if call_with %}
-{% if cobalt_type == "void" %}
-{{ call_void_function(function_name, arguments) }}
+{% do arguments_list.append('&exception_state') if raises_exception %}
+{%- endmacro %}
+
+{% macro call_nonvoid_function(return_type, function_name, arguments,
+                               impl_class, is_static) %}
+  if (!exception_state.is_exception_set()) {
+{% if not is_static %}
+    ToJSValue(context,
+              impl->{{function_name}}({{arguments|join(", ")}}),
+              &result_value);
 {% else %}
-{{ call_nonvoid_function(cobalt_type, function_name, arguments) }}
+    ToJSValue(context,
+              {{impl_class}}::{{function_name}}({{arguments|join(', ')}}),
+              &result_value);
+{% endif %}
+  }
+{%- endmacro %}
+
+{% macro call_void_function(function_name, arguments, impl_class, is_static,
+                            cobalt_impl_prefix) %}
+{% if not is_static %}
+  {{cobalt_impl_prefix}}impl->{{function_name}}({{arguments|join(", ")}});
+{% else %}
+  {{impl_class}}::{{function_name}}({{arguments|join(', ')}});
+{% endif %}
+  result_value.set(JS::UndefinedHandleValue);
+{%- endmacro %}
+
+{% macro get_impl_class_instance(impl_class) %}
+  WrapperPrivate* wrapper_private =
+      WrapperPrivate::GetFromObject(context, object);
+  {{impl_class}}* impl =
+      wrapper_private->wrappable<{{impl_class}}>().get();
+{%- endmacro %}
+
+{% macro static_function_prologue() %}
+  MozjsExceptionState exception_state(context);
+  JS::RootedValue result_value(context);
+{% endmacro %}
+
+{% macro nonstatic_function_prologue(impl_class) %}
+{{ static_function_prologue() }}
+{{ get_impl_class_instance(impl_class) }}
+{%- endmacro %}
+
+{#
+ # Call a function on an instance of a Cobalt platform object.
+ #}
+{% macro call_cobalt_function(impl_class, cobalt_type, function_name, arguments,
+                              raises_exception, call_with, is_static,
+                              cobalt_impl_prefix) %}
+{{ add_extra_arguments(arguments, raises_exception, call_with) }}
+{% if cobalt_type == "void" %}
+{{ call_void_function(function_name, arguments, impl_class, is_static,
+                      cobalt_impl_prefix) -}}
+{% else %}
+{{ call_nonvoid_function(cobalt_type, function_name, arguments, impl_class,
+                         is_static) -}}
 {% endif %}
 {% endmacro %}
+
+{#
+ # Function body for constructor bindings.
+ # Parameters:
+ #     constructor: The constructor context object
+ #}
+{% macro constructor_implementation(constructor) %}
+  MozjsExceptionState exception_state(context);
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+{% call(arguments_list) extract_arguments(constructor) %}
+{{ add_extra_arguments(arguments_list, constructor.raises_exception,
+                       constructor.call_with) }}
+  scoped_refptr<{{impl_class}}> new_object =
+      new {{impl_class}}({{arguments_list|join(', ')}});
+  JS::RootedValue result_value(context);
+  ToJSValue(context, new_object, &result_value);
+  DCHECK(result_value.isObject());
+  JS::RootedObject result_object(context, JSVAL_TO_OBJECT(result_value));
+  args.rval().setObject(*result_object);
+  return true;
+{%- endcall %}
+{%- endmacro %}
+
+{#
+ # Function body for overload resolution function.
+ # Parameters:
+ #     overload_context: The overload context object.
+ #     bound_function_prefix: The prefix of the function to be called on
+ #         resolution. The overload index will be appended to this.
+ #}
+{% macro overload_resolution_implementation(
+      overload_context, bound_function_prefix) %}
+  JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
+  switch(argc) {
+{% for length, distinguishing_argument_index, resolution_tests in
+       overload_context.overload_resolution_by_length %}
+    case({{length}}): {
+      // Overload resolution algorithm details found here:
+      //     http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+{# In the case there is only one resolution condition, we don't need the arg. #}
+{% if resolution_tests|length > 1 %}
+      JS::RootedValue arg(context, args[{{distinguishing_argument_index}}]);
+      MozjsGlobalObjectProxy* global_object_proxy =
+          static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+      WrapperFactory* wrapper_factory = global_object_proxy->wrapper_factory();
+{% endif %}
+{% for test, overload in resolution_tests %}
+      if ({{test("arg")}}) {
+        return {{bound_function_prefix}}{{overload.overload_index}}(
+                  context, argc, vp);
+      }
+{% endfor %}
+      break;
+    }
+{% endfor %}
+  }
+  // Invalid number of args
+  // http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm
+  // 4. If S is empty, then throw a TypeError.
+  MozjsExceptionState exception_state(context);
+  exception_state.SetSimpleException(
+      script::ExceptionState::kTypeError, "Invalid number of arguments.");
+  return false;
+{%- endmacro %}
diff --git a/src/cobalt/bindings/run_cobalt_bindings_tests.bat b/src/cobalt/bindings/run_cobalt_bindings_tests.bat
new file mode 100644
index 0000000..e26fc8d
--- /dev/null
+++ b/src/cobalt/bindings/run_cobalt_bindings_tests.bat
@@ -0,0 +1,18 @@
+@rem
+@rem Copyright 2016 Google Inc. All Rights Reserved.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem     http://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@python run_cobalt_bindings_tests.py jsc %*
+@python run_cobalt_bindings_tests.py mozjs %*
diff --git a/src/cobalt/bindings/testing/DOMStringTestInterface.idl b/src/cobalt/bindings/testing/DOMStringTestInterface.idl
index 1c03de6..40667eb 100644
--- a/src/cobalt/bindings/testing/DOMStringTestInterface.idl
+++ b/src/cobalt/bindings/testing/DOMStringTestInterface.idl
@@ -17,6 +17,7 @@
 interface DOMStringTestInterface {
   attribute DOMString property;
   readonly attribute DOMString readOnlyProperty;
+  readonly attribute DOMString readOnlyTokenProperty;
   [TreatNullAs=EmptyString] attribute DOMString nullIsEmptyProperty;
   [TreatUndefinedAs=EmptyString] attribute DOMString undefinedIsEmptyProperty;
   [TreatUndefinedAs=EmptyString] attribute DOMString? nullableUndefinedIsEmptyProperty;
diff --git a/src/cobalt/bindings/testing/DerivedInterface.idl b/src/cobalt/bindings/testing/DerivedInterface.idl
index 45127a9..810d333 100644
--- a/src/cobalt/bindings/testing/DerivedInterface.idl
+++ b/src/cobalt/bindings/testing/DerivedInterface.idl
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+[Constructor]
 interface DerivedInterface : BaseInterface {
   readonly attribute DOMString derivedAttribute;
   void derivedOperation();
diff --git a/src/cobalt/bindings/testing/IndexedGetterInterface.idl b/src/cobalt/bindings/testing/IndexedGetterInterface.idl
index c8c1f8a..bd0cc05 100644
--- a/src/cobalt/bindings/testing/IndexedGetterInterface.idl
+++ b/src/cobalt/bindings/testing/IndexedGetterInterface.idl
@@ -18,4 +18,5 @@
   readonly attribute unsigned long length;
   getter unsigned long indexedGetter(unsigned long index);
   setter void indexedSetter(unsigned long index, unsigned long value);
+  deleter void indexedDeleter(unsigned long index);
 };
diff --git a/src/cobalt/bindings/testing/NumericTypesTestInterface.idl b/src/cobalt/bindings/testing/NumericTypesTestInterface.idl
index 320d6b9..96d9bd6 100644
--- a/src/cobalt/bindings/testing/NumericTypesTestInterface.idl
+++ b/src/cobalt/bindings/testing/NumericTypesTestInterface.idl
@@ -39,6 +39,14 @@
   void unsignedLongArgumentOperation(unsigned long arg1);
   attribute unsigned long unsignedLongProperty;
 
+  long long longLongReturnOperation();
+  void longLongArgumentOperation(long long arg1);
+  attribute long long longLongProperty;
+
+  unsigned long long unsignedLongLongReturnOperation();
+  void unsignedLongLongArgumentOperation(unsigned long long arg1);
+  attribute unsigned long long unsignedLongLongProperty;
+
   double doubleReturnOperation();
   void doubleArgumentOperation(double arg1);
   attribute double doubleProperty;
diff --git a/src/cobalt/bindings/testing/OperationsTestInterface.idl b/src/cobalt/bindings/testing/OperationsTestInterface.idl
index 3dc3507..264f39e 100644
--- a/src/cobalt/bindings/testing/OperationsTestInterface.idl
+++ b/src/cobalt/bindings/testing/OperationsTestInterface.idl
@@ -41,6 +41,7 @@
   // double and long are not distinguishable, but because this is a static
   // function it is part of the same overload set as the one that takes long.
   static void overloadedFunction(double arg);
+  static void overloadedFunction(double arg1, double arg2);
 
   void overloadedNullable(long arg);
   void overloadedNullable(boolean? arg);
diff --git a/src/cobalt/bindings/testing/PutForwardsInterface.idl b/src/cobalt/bindings/testing/PutForwardsInterface.idl
index e488252..d8bf8ab 100644
--- a/src/cobalt/bindings/testing/PutForwardsInterface.idl
+++ b/src/cobalt/bindings/testing/PutForwardsInterface.idl
@@ -16,4 +16,6 @@
 interface PutForwardsInterface {
   [PutForwards=arbitraryProperty]
   readonly attribute ArbitraryInterface forwardingAttribute;
+  [PutForwards=arbitraryProperty]
+  static readonly attribute ArbitraryInterface staticForwardingAttribute;
 };
diff --git a/src/cobalt/bindings/testing/StaticPropertiesInterface.idl b/src/cobalt/bindings/testing/StaticPropertiesInterface.idl
index e0a8fb2..2a73da8 100644
--- a/src/cobalt/bindings/testing/StaticPropertiesInterface.idl
+++ b/src/cobalt/bindings/testing/StaticPropertiesInterface.idl
@@ -15,5 +15,9 @@
  */
 interface StaticPropertiesInterface {
   static void staticFunction();
+  static void staticFunction(long arg);
+  static void staticFunction(DOMString arg);
+  static void staticFunction(long arg1, long arg2, long arg3);
+  static void staticFunction(long arg1, long arg2, ArbitraryInterface arg3);
   static attribute DOMString staticAttribute;
 };
diff --git a/src/cobalt/bindings/testing/UnionTypesInterface.idl b/src/cobalt/bindings/testing/UnionTypesInterface.idl
index 33f9854..e53b034 100644
--- a/src/cobalt/bindings/testing/UnionTypesInterface.idl
+++ b/src/cobalt/bindings/testing/UnionTypesInterface.idl
@@ -18,4 +18,5 @@
   attribute (DOMString or boolean or ArbitraryInterface or long) unionProperty;
   attribute (double or DOMString?) unionWithNullableMemberProperty;
   attribute (double or DOMString)? nullableUnionProperty;
+  attribute (BaseInterface or DOMString) unionBaseProperty;
 };
diff --git a/src/cobalt/bindings/testing/dom_string_bindings_test.cc b/src/cobalt/bindings/testing/dom_string_bindings_test.cc
index f8614dc..06a9595 100644
--- a/src/cobalt/bindings/testing/dom_string_bindings_test.cc
+++ b/src/cobalt/bindings/testing/dom_string_bindings_test.cc
@@ -58,6 +58,15 @@
   EXPECT_TRUE(EvaluateScript("test.readOnlyProperty = \"foo\";", NULL));
 }
 
+TEST_F(DOMStringBindingsTest, GetReadOnlyTokenProperty) {
+  EXPECT_CALL(test_mock(), read_only_token_property())
+      .WillOnce(Return(base::Token("mock_value")));
+
+  std::string result;
+  EXPECT_TRUE(EvaluateScript("test.readOnlyTokenProperty;", &result));
+  EXPECT_STREQ("mock_value", result.c_str());
+}
+
 TEST_F(DOMStringBindingsTest, SetNull) {
   EXPECT_CALL(test_mock(), set_property("null"));
 
diff --git a/src/cobalt/bindings/testing/dom_string_test_interface.h b/src/cobalt/bindings/testing/dom_string_test_interface.h
index f257d2f..7bcd05d 100644
--- a/src/cobalt/bindings/testing/dom_string_test_interface.h
+++ b/src/cobalt/bindings/testing/dom_string_test_interface.h
@@ -20,6 +20,7 @@
 #include <string>
 
 #include "base/optional.h"
+#include "cobalt/base/token.h"
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -36,6 +37,9 @@
   // readonly attribute DOMString readOnlyProperty
   MOCK_CONST_METHOD0(read_only_property, std::string());
 
+  // readonly attribute DOMString readOnlyTokenProperty
+  MOCK_CONST_METHOD0(read_only_token_property, base::Token());
+
   MOCK_CONST_METHOD0(null_is_empty_property, std::string());
   MOCK_METHOD1(set_null_is_empty_property, void(const std::string&));
 
diff --git a/src/cobalt/bindings/testing/getter_setter_test.cc b/src/cobalt/bindings/testing/getter_setter_test.cc
index 265f28e..24654d5 100644
--- a/src/cobalt/bindings/testing/getter_setter_test.cc
+++ b/src/cobalt/bindings/testing/getter_setter_test.cc
@@ -37,17 +37,34 @@
 namespace testing {
 
 namespace {
-typedef InterfaceBindingsTest<AnonymousIndexedGetterInterface>
+// Use this fixture to create a new MockT object with a BaseClass wrapper, and
+// bind the wrapper to the javascript variable "test".
+template <class MockT>
+class GetterSetterBindingsTestBase : public BindingsTestBase {
+ public:
+  GetterSetterBindingsTestBase()
+      : test_mock_(new ::testing::NiceMock<MockT>()) {
+    global_object_proxy_->Bind("test", make_scoped_refptr<MockT>((test_mock_)));
+  }
+
+  MockT& test_mock() { return *test_mock_.get(); }
+
+  const scoped_refptr<MockT> test_mock_;
+};
+
+typedef GetterSetterBindingsTestBase<AnonymousIndexedGetterInterface>
     AnonymousIndexedGetterBindingsTest;
-typedef InterfaceBindingsTest<AnonymousNamedIndexedGetterInterface>
+typedef GetterSetterBindingsTestBase<AnonymousNamedIndexedGetterInterface>
     AnonymousNamedIndexedGetterBindingsTest;
-typedef InterfaceBindingsTest<AnonymousNamedGetterInterface>
+typedef GetterSetterBindingsTestBase<AnonymousNamedGetterInterface>
     AnonymousNamedGetterBindingsTest;
-typedef InterfaceBindingsTest<DerivedGetterSetterInterface>
+typedef GetterSetterBindingsTestBase<DerivedGetterSetterInterface>
     DerivedGetterSetterBindingsTest;
-typedef InterfaceBindingsTest<IndexedGetterInterface> IndexedGetterBindingsTest;
-typedef InterfaceBindingsTest<NamedGetterInterface> NamedGetterBindingsTest;
-typedef InterfaceBindingsTest<NamedIndexedGetterInterface>
+typedef GetterSetterBindingsTestBase<IndexedGetterInterface>
+    IndexedGetterBindingsTest;
+typedef GetterSetterBindingsTestBase<NamedGetterInterface>
+    NamedGetterBindingsTest;
+typedef GetterSetterBindingsTestBase<NamedIndexedGetterInterface>
     NamedIndexedGetterBindingsTest;
 
 class NamedPropertiesEnumerator {
@@ -67,134 +84,149 @@
 }  // namespace
 
 TEST_F(IndexedGetterBindingsTest, IndexedGetter) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
+  ON_CALL(test_mock(), IndexedGetter(_)).WillByDefault(ReturnArg<0>());
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
-  EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>());
+  EXPECT_CALL(test_mock(), IndexedGetter(4)).Times(1);
   EXPECT_TRUE(EvaluateScript("test[4];", &result));
   EXPECT_STREQ("4", result.c_str());
 
-  EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>());
+  EXPECT_CALL(test_mock(), IndexedGetter(6)).Times(1);
   EXPECT_TRUE(EvaluateScript("test.indexedGetter(6);", &result));
   EXPECT_STREQ("6", result.c_str());
 }
 
 TEST_F(IndexedGetterBindingsTest, IndexedGetterOutOfRange) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
+  ON_CALL(test_mock(), IndexedGetter(_)).WillByDefault(ReturnArg<0>());
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
+  EXPECT_CALL(test_mock(), IndexedGetter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[20];", &result));
   EXPECT_STREQ("undefined", result.c_str());
 
-  EXPECT_CALL(test_mock(), IndexedGetter(_)).WillOnce(ReturnArg<0>());
+  EXPECT_CALL(test_mock(), IndexedGetter(20)).Times(1);
   EXPECT_TRUE(EvaluateScript("test.indexedGetter(20);", &result));
   EXPECT_STREQ("20", result.c_str());
 }
 
 TEST_F(IndexedGetterBindingsTest, IndexedSetter) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
-  EXPECT_CALL(test_mock(), IndexedSetter(4, 100));
+  EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1);
   EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL));
 
-  EXPECT_CALL(test_mock(), IndexedSetter(4, 100));
+  EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1);
   EXPECT_TRUE(EvaluateScript("test.indexedSetter(4, 100);", NULL));
 }
 
+#if defined(ENGINE_SUPPORTS_INDEXED_DELETERS)
 TEST_F(IndexedGetterBindingsTest, IndexedDeleter) {
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
+  EXPECT_CALL(test_mock(), IndexedDeleter(4)).Times(1);
   EXPECT_TRUE(EvaluateScript("delete test[4];", NULL));
 }
 
 TEST_F(IndexedGetterBindingsTest, IndexedDeleterOutOfRange) {
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(1));
+  ON_CALL(test_mock(), length()).WillByDefault(Return(1));
+  EXPECT_CALL(test_mock(), IndexedDeleter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("delete test[4];", NULL));
 }
+#endif
 
 TEST_F(IndexedGetterBindingsTest, IndexedSetterOutOfRange) {
-  InSequence dummy;
+  ON_CALL(test_mock(), length()).WillByDefault(Return(1));
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(1));
+  InSequence dummy;
   EXPECT_CALL(test_mock(), IndexedSetter(_, _)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL));
 
-  EXPECT_CALL(test_mock(), IndexedSetter(4, 100));
+  EXPECT_CALL(test_mock(), IndexedSetter(4, 100)).Times(1);
   EXPECT_TRUE(EvaluateScript("test.indexedSetter(4, 100);", NULL));
 }
 
 TEST_F(NamedGetterBindingsTest, NamedGetter) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
+      .WillByDefault(Return(true));
+  ON_CALL(test_mock(), NamedGetter(std::string("foo")))
+      .WillByDefault(Return(std::string("bar")));
+  ON_CALL(test_mock(), NamedGetter(std::string("bar")))
+      .WillByDefault(Return(std::string("foo")));
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
-      .WillOnce(Return(true));
-  EXPECT_CALL(test_mock(), NamedGetter(std::string("foo")))
-      .WillOnce(Return(std::string("bar")));
+  EXPECT_CALL(test_mock(), NamedGetter(std::string("foo"))).Times(1);
   EXPECT_TRUE(EvaluateScript("test[\"foo\"];", &result));
   EXPECT_STREQ("bar", result.c_str());
 
-  EXPECT_CALL(test_mock(), NamedGetter(std::string("bar")))
-      .WillOnce(Return(std::string("foo")));
+  EXPECT_CALL(test_mock(), NamedGetter(std::string("bar"))).Times(1);
   EXPECT_TRUE(EvaluateScript("test.namedGetter(\"bar\");", &result));
   EXPECT_STREQ("foo", result.c_str());
 }
 
 TEST_F(NamedGetterBindingsTest, NamedGetterUnsupportedName) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(_)).WillByDefault(Return(false));
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
-      .WillOnce(Return(false));
+  EXPECT_CALL(test_mock(), NamedGetter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[\"foo\"];", &result));
   EXPECT_STREQ("undefined", result.c_str());
 }
 
 TEST_F(NamedGetterBindingsTest, NamedSetter) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
+      .WillByDefault(Return(true));
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar")));
+  EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar")))
+      .Times(1);
   EXPECT_TRUE(EvaluateScript("test[\"foo\"] = \"bar\";", NULL));
 
-  EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar")));
+  EXPECT_CALL(test_mock(), NamedSetter(std::string("foo"), std::string("bar")))
+      .Times(1);
   EXPECT_TRUE(EvaluateScript("test.namedSetter(\"foo\", \"bar\");", NULL));
 }
 
 TEST_F(NamedGetterBindingsTest, NamedDeleter) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
+      .WillByDefault(Return(true));
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
-      .WillOnce(Return(true));
-  EXPECT_CALL(test_mock(), NamedDeleter(std::string("foo")));
+  EXPECT_CALL(test_mock(), NamedDeleter(std::string("foo"))).Times(1);
   EXPECT_TRUE(EvaluateScript("delete test.foo;", NULL));
 
-  EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar")));
+  EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))).Times(1);
   EXPECT_TRUE(EvaluateScript("test.namedDeleter(\"bar\");", NULL));
 }
 
 TEST_F(NamedGetterBindingsTest, NamedDeleterUnsupportedName) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(_)).WillByDefault(Return(false));
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
-      .WillOnce(Return(false));
+  EXPECT_CALL(test_mock(), NamedDeleter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("delete test.foo;", NULL));
 
-  EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar")));
+  EXPECT_CALL(test_mock(), NamedDeleter(std::string("bar"))).Times(1);
   EXPECT_TRUE(EvaluateScript("test.namedDeleter(\"bar\");", NULL));
 }
 
 TEST_F(NamedGetterBindingsTest, NamedDeleterIndexProperty) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("1")))
+      .WillByDefault(Return(true));
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), CanQueryNamedProperty(std::string("1")))
-      .WillOnce(Return(true));
-  EXPECT_CALL(test_mock(), NamedDeleter(std::string("1")));
+  EXPECT_CALL(test_mock(), NamedDeleter(std::string("1"))).Times(1);
   EXPECT_TRUE(EvaluateScript("delete test[1];", NULL));
 }
 
 TEST_F(NamedGetterBindingsTest, IndexConvertsToNamedProperty) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("5")))
+      .WillByDefault(Return(true));
   InSequence dummy;
 
   EXPECT_CALL(test_mock(), NamedSetter(std::string("5"), std::string("bar")));
@@ -213,79 +245,106 @@
   InSequence dummy;
 
   std::string result;
+  EXPECT_CALL(test_mock(), NamedGetter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[\"toString\"]();", &result));
   EXPECT_STREQ("[object NamedIndexedGetterInterface]", result.c_str());
 }
 
 TEST_F(AnonymousNamedIndexedGetterBindingsTest, EnumeratedPropertiesOrdering) {
   NamedPropertiesEnumerator enumerator(2);
+  ON_CALL(test_mock(), length()).WillByDefault(Return(2));
+  ON_CALL(test_mock(), EnumerateNamedProperties(_))
+      .WillByDefault(Invoke(
+          &enumerator, &NamedPropertiesEnumerator::EnumerateNamedProperties));
 
   std::string result;
-  EXPECT_CALL(test_mock(), length()).Times(3).WillRepeatedly(Return(2));
-  EXPECT_CALL(test_mock(), EnumerateNamedProperties(_))
-      .WillOnce(Invoke(&enumerator,
-                       &NamedPropertiesEnumerator::EnumerateNamedProperties));
   EXPECT_TRUE(
       EvaluateScript("var properties = [];"
                      "for (p in test) { properties.push(p); }"
                      "properties;",
                      &result));
-
   // Indexed properties should come first, then named properties, and then
   // other "regular" properties that are defined on the interface;
-  EXPECT_STREQ("0,1,property_a,property_b,length", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties.length;", &result));
+  EXPECT_STREQ("5", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[0];", &result));
+  EXPECT_STREQ("0", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[1];", &result));
+  EXPECT_STREQ("1", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[2];", &result));
+  EXPECT_STREQ("property_a", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[3];", &result));
+  EXPECT_STREQ("property_b", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[4];", &result));
+  EXPECT_STREQ("length", result.c_str());
 }
 
 TEST_F(AnonymousIndexedGetterBindingsTest, EnumerateIndexedProperties) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(4));
   std::string result;
-  EXPECT_CALL(test_mock(), length()).Times(5).WillRepeatedly(Return(4));
   EXPECT_TRUE(
       EvaluateScript("var properties = [];"
                      "for (p in test) { properties.push(p); }"
                      "properties;",
                      &result));
 
-  EXPECT_STREQ("0,1,2,3,length", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties.length;", &result));
+  EXPECT_STREQ("5", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[0];", &result));
+  EXPECT_STREQ("0", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[1];", &result));
+  EXPECT_STREQ("1", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[2];", &result));
+  EXPECT_STREQ("2", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[3];", &result));
+  EXPECT_STREQ("3", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[4];", &result));
+  EXPECT_STREQ("length", result.c_str());
 }
 
 TEST_F(AnonymousNamedGetterBindingsTest, EnumerateNamedProperties) {
   NamedPropertiesEnumerator enumerator(4);
+  ON_CALL(test_mock(), EnumerateNamedProperties(_))
+      .WillByDefault(Invoke(
+          &enumerator, &NamedPropertiesEnumerator::EnumerateNamedProperties));
 
   std::string result;
-  EXPECT_CALL(test_mock(), EnumerateNamedProperties(_))
-      .WillOnce(Invoke(&enumerator,
-                       &NamedPropertiesEnumerator::EnumerateNamedProperties));
   EXPECT_TRUE(
       EvaluateScript("var properties = [];"
-                     "for (p in test) { properties.push(p); }"
-                     "properties;",
-                     &result));
+                     "for (p in test) { properties.push(p); }"));
 
-  EXPECT_STREQ("property_a,property_b,property_c,property_d", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties.length;", &result));
+  EXPECT_STREQ("4", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[0];", &result));
+  EXPECT_STREQ("property_a", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[1];", &result));
+  EXPECT_STREQ("property_b", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[2];", &result));
+  EXPECT_STREQ("property_c", result.c_str());
+  EXPECT_TRUE(EvaluateScript("properties[3];", &result));
+  EXPECT_STREQ("property_d", result.c_str());
 }
 
 TEST_F(AnonymousIndexedGetterBindingsTest, IndexedGetter) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
+  ON_CALL(test_mock(), AnonymousIndexedGetter(_)).WillByDefault(ReturnArg<0>());
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
-  EXPECT_CALL(test_mock(), AnonymousIndexedGetter(_)).WillOnce(ReturnArg<0>());
   EXPECT_TRUE(EvaluateScript("test[4];", &result));
   EXPECT_STREQ("4", result.c_str());
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
-  EXPECT_CALL(test_mock(), AnonymousIndexedGetter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[10];", NULL));
 }
 
 TEST_F(AnonymousIndexedGetterBindingsTest, IndexedSetter) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
+
   InSequence dummy;
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
   EXPECT_CALL(test_mock(), AnonymousIndexedSetter(4, 100));
   EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL));
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
   EXPECT_CALL(test_mock(), AnonymousIndexedSetter(_, _)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[10] = 100;", NULL));
 }
@@ -313,6 +372,8 @@
 }
 
 TEST_F(AnonymousNamedGetterBindingsTest, NamedSetter) {
+  ON_CALL(test_mock(), CanQueryNamedProperty(std::string("foo")))
+      .WillByDefault(Return(true));
   InSequence dummy;
 
   EXPECT_CALL(test_mock(),
@@ -321,16 +382,15 @@
 }
 
 TEST_F(DerivedGetterSetterBindingsTest, OverridesGetterAndSetter) {
+  ON_CALL(test_mock(), length()).WillByDefault(Return(10));
   InSequence dummy;
 
   std::string result;
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
   EXPECT_CALL(test_mock(), DerivedIndexedGetter(4)).WillOnce(Return(100));
   EXPECT_CALL(test_mock(), IndexedGetter(_)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[4] == 100;", &result));
   EXPECT_STREQ("true", result.c_str());
 
-  EXPECT_CALL(test_mock(), length()).WillOnce(Return(10));
   EXPECT_CALL(test_mock(), DerivedIndexedSetter(4, 100));
   EXPECT_CALL(test_mock(), IndexedSetter(_, _)).Times(0);
   EXPECT_TRUE(EvaluateScript("test[4] = 100;", NULL));
@@ -356,6 +416,8 @@
 }
 
 TEST_F(DerivedGetterSetterBindingsTest, NamedSetterDoesNotShadowProperties) {
+  EXPECT_CALL(test_mock(), CanQueryNamedProperty(_))
+      .Times(::testing::AtLeast(0));
   InSequence dummy;
 
   std::string result;
diff --git a/src/cobalt/bindings/testing/indexed_getter_interface.h b/src/cobalt/bindings/testing/indexed_getter_interface.h
index 2b70e54..5979e8f 100644
--- a/src/cobalt/bindings/testing/indexed_getter_interface.h
+++ b/src/cobalt/bindings/testing/indexed_getter_interface.h
@@ -29,6 +29,7 @@
   MOCK_METHOD0(length, uint32_t());
   MOCK_METHOD1(IndexedGetter, uint32_t(uint32_t));
   MOCK_METHOD2(IndexedSetter, void(uint32_t, uint32_t));
+  MOCK_METHOD1(IndexedDeleter, void(uint32_t));
 
   DEFINE_WRAPPABLE_TYPE(IndexedGetterInterface);
 };
diff --git a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
index d246155..88e92d0 100644
--- a/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/numeric_type_bindings_test.cc
@@ -45,12 +45,30 @@
 template <typename T>
 class FloatingPointTypeBindingsTest : public NumericTypeBindingsTest<T> {};
 
+#if defined(ENGINE_SUPPORTS_INT64)
+template <typename T>
+class LargeIntegerTypeBindingsTest : public NumericTypeBindingsTest<T> {};
+
+typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest,
+                         UnsignedShortTypeTest, LongTypeTest,
+                         UnsignedLongTypeTest, LongLongTypeTest,
+                         UnsignedLongLongTypeTest, DoubleTypeTest> NumericTypes;
+
+typedef ::testing::Types<LongLongTypeTest, UnsignedLongLongTypeTest>
+    LargeIntegerTypes;
+
+TYPED_TEST_CASE(LargeIntegerTypeBindingsTest, LargeIntegerTypes);
+#else
 typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest,
                          UnsignedShortTypeTest, LongTypeTest,
                          UnsignedLongTypeTest, DoubleTypeTest> NumericTypes;
+#endif  // ENGINE_SUPPORTS_INT64
+// Not including long longs in IntegerTypes, due to different casting
+// behaviours.
 typedef ::testing::Types<ByteTypeTest, OctetTypeTest, ShortTypeTest,
                          UnsignedShortTypeTest, LongTypeTest,
                          UnsignedLongTypeTest> IntegerTypes;
+
 typedef ::testing::Types<DoubleTypeTest, UnrestrictedDoubleTypeTest>
     FloatingPointTypes;
 TYPED_TEST_CASE(NumericTypeBindingsTest, NumericTypes);
@@ -141,7 +159,6 @@
   EXPECT_CALL(this->test_mock(), mock_set_property(0));
   EXPECT_TRUE(this->EvaluateScript(
       StringPrintf("test.%sProperty = 0;", TypeParam::type_string()), NULL));
-
   EXPECT_CALL(this->test_mock(), mock_set_property(TypeParam::min_value()));
   EXPECT_TRUE(this->EvaluateScript(
       StringPrintf("test.%sProperty = %s;", TypeParam::type_string(),
@@ -210,6 +227,196 @@
       NULL));
 }
 
+#if defined(ENGINE_SUPPORTS_INT64)
+TYPED_TEST(LargeIntegerTypeBindingsTest, PropertyValueRange) {
+  InSequence in_sequence_dummy;
+
+  std::string result;
+  std::string script =
+      StringPrintf("test.%sProperty;", TypeParam::type_string());
+
+  EXPECT_CALL(this->test_mock(), mock_get_property()).WillOnce(Return(0));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ("0", result.c_str());
+
+  EXPECT_CALL(this->test_mock(), mock_get_property())
+      .WillOnce(Return(TypeParam::min_value()));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(TypeParam::min_value_string(), result.c_str());
+
+  EXPECT_CALL(this->test_mock(), mock_get_property())
+      .WillOnce(Return(TypeParam::max_value()));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(TypeParam::max_value_string(), result.c_str());
+}
+
+// These tests require converting LargeIntegers (e.g. long long) to
+// JSValues using the IDL spec:
+// https://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-long-long
+// This preserves exactly the range (-(2^53 - 1), 2^53 -1) and
+// approximately outside that range (see the spec for details).
+TYPED_TEST(LargeIntegerTypeBindingsTest, ReturnValueRange) {
+  InSequence in_sequence_dummy;
+
+  // Exactly preserve 0.
+  std::string result;
+  std::string script =
+      StringPrintf("test.%sReturnOperation();", TypeParam::type_string());
+  EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+      .WillOnce(Return(0));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ("0", result.c_str());
+
+  // Approximately preserve int64_t/uint64_t min.
+  EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+      .WillOnce(Return(TypeParam::min_value()));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(TypeParam::min_value_string(), result.c_str());
+
+  // Approximately preserve int64_t/uint64_t max.
+  EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+      .WillOnce(Return(TypeParam::max_value()));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(TypeParam::max_value_string(), result.c_str());
+
+  // Exactly preserve 2^53 - 1.
+  const uint64_t kRangeBound = (1ll << 53) - 1;
+  std::string expected_result = StringPrintf("%" PRIu64 "", kRangeBound);
+  EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+      .WillOnce(Return(kRangeBound));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(expected_result.c_str(), result.c_str());
+
+  // Signed : exactly preserve -(2^53 - 1).
+  if (TypeParam::min_value() < 0) {
+    expected_result = StringPrintf("-%" PRIu64 "", kRangeBound);
+    EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+        .WillOnce(Return(-kRangeBound));
+    EXPECT_TRUE(this->EvaluateScript(script, &result));
+    EXPECT_STREQ(expected_result.c_str(), result.c_str());
+  }
+
+  // Exactly preserve 9223372036854775000 (between 2^53 and int64_t max).
+  expected_result = "9223372036854775000";
+  EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+      .WillOnce(Return(9223372036854775000ll));
+  EXPECT_TRUE(this->EvaluateScript(script, &result));
+  EXPECT_STREQ(expected_result.c_str(), result.c_str());
+
+  // Unsigned : exactly preserve 18446744073709550000 (between 2^53
+  // and uint64_t max).
+  if (TypeParam::min_value() >= 0) {
+    expected_result = "18446744073709550000";
+    EXPECT_CALL(this->test_mock(), MockReturnValueOperation())
+        .WillOnce(Return(18446744073709550000l));
+    EXPECT_TRUE(this->EvaluateScript(script, &result));
+    EXPECT_STREQ(expected_result.c_str(), result.c_str());
+  }
+}
+
+// These tests require converting JSValues to LargeIntegers (e.g. long long)
+// using the IDL spec:
+// https://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-long-long
+// This preserves exactly the range (-(2^53 - 1), 2^53 -1),
+// and for all other values does the following:
+// For input value V.
+// x = ToNumber(V)
+// If x is Nan, +inf, -inf return 0
+// ...Handle extended_attribute special cases...
+// 5. x = sign(x) * floor(abs(x))
+// 6. x = x mod 2^64
+// 7. If x >= 2^63, x = x - 2^64 (for signed only)
+// 8. Return the IDL long long value that represents the same numeric
+//    value as x.
+TYPED_TEST(LargeIntegerTypeBindingsTest, SetPropertyRange) {
+  InSequence in_sequence_dummy;
+
+  // Exactly preserve 0.
+  EXPECT_CALL(this->test_mock(), mock_set_property(0));
+  EXPECT_TRUE(this->EvaluateScript(
+      StringPrintf("test.%sProperty = 0;", TypeParam::type_string()), NULL));
+
+  // Exactly preserve 2^53 - 1.
+  EXPECT_CALL(this->test_mock(), mock_set_property((1ll << 53) - 1));
+  EXPECT_TRUE(
+      this->EvaluateScript(StringPrintf("test.%sProperty = 9007199254740991;",
+                                        TypeParam::type_string()),
+                           NULL));
+
+  // Signed : exactly preserve -(2^53 - 1).
+  if (TypeParam::min_value() < 0) {
+    EXPECT_CALL(this->test_mock(), mock_set_property(-((1ll << 53) - 1)));
+    EXPECT_TRUE(this->EvaluateScript(
+        StringPrintf("test.%sProperty = -9007199254740991;",
+                     TypeParam::type_string()),
+        NULL));
+  }
+
+  // Send 9223372036854775000 (between 2^53 and int64_t max) to
+  // 9223372036854774784.
+  EXPECT_CALL(this->test_mock(), mock_set_property(9223372036854774784));
+  EXPECT_TRUE(this->EvaluateScript(
+      StringPrintf("test.%sProperty = 9223372036854775000;",
+                   TypeParam::type_string()),
+      NULL));
+
+  // Unsigned : send 18446744073709550000 (between 2^53
+  // and uint64_t max) to 18446744073709549568.
+  if (TypeParam::min_value() >= 0) {
+    EXPECT_CALL(this->test_mock(), mock_set_property(18446744073709549568));
+    EXPECT_TRUE(this->EvaluateScript(
+        StringPrintf("test.%sProperty = 18446744073709550000;",
+                     TypeParam::type_string()),
+        NULL));
+  }
+}
+
+// These tests also rely on FromJSValue (similar to above).
+TYPED_TEST(LargeIntegerTypeBindingsTest, ArgumentOperationRange) {
+  InSequence in_sequence_dummy;
+
+  // Exactly preserve 0.
+  EXPECT_CALL(this->test_mock(), MockArgumentOperation(0));
+  EXPECT_TRUE(this->EvaluateScript(
+      StringPrintf("test.%sArgumentOperation(0);", TypeParam::type_string()),
+      NULL));
+
+  // Exactly preserve 2^53 - 1.
+  EXPECT_CALL(this->test_mock(), MockArgumentOperation((1ll << 53) - 1));
+  EXPECT_TRUE(this->EvaluateScript(
+      StringPrintf("test.%sArgumentOperation(9007199254740991);",
+                   TypeParam::type_string()),
+      NULL));
+
+  // Signed : exactly preserve -(2^53 - 1).
+  if (TypeParam::min_value() < 0) {
+    EXPECT_CALL(this->test_mock(), MockArgumentOperation(-((1ll << 53) - 1)));
+    EXPECT_TRUE(this->EvaluateScript(
+        StringPrintf("test.%sArgumentOperation(-9007199254740991);",
+                     TypeParam::type_string()),
+        NULL));
+  }
+
+  // Send 9223372036854775000 (between 2^53 and int64_t max) to
+  // 9223372036854774784.
+  EXPECT_CALL(this->test_mock(), MockArgumentOperation(9223372036854774784));
+  EXPECT_TRUE(this->EvaluateScript(
+      StringPrintf("test.%sArgumentOperation(9223372036854775000);",
+                   TypeParam::type_string()),
+      NULL));
+
+  // Unsigned : send 18446744073709550000 (between 2^53
+  // and uint64_t max) to 18446744073709549568.
+  if (TypeParam::min_value() >= 0) {
+    EXPECT_CALL(this->test_mock(), MockArgumentOperation(18446744073709549568));
+    EXPECT_TRUE(this->EvaluateScript(
+        StringPrintf("test.%sArgumentOperation(18446744073709550000);",
+                     TypeParam::type_string()),
+        NULL));
+  }
+}
+#endif  // ENGINE_SUPPORTS_INT64
+
 TYPED_TEST(FloatingPointTypeBindingsTest, NonFiniteValues) {
   InSequence in_sequence_dummy;
   if (TypeParam::is_restricted()) {
diff --git a/src/cobalt/bindings/testing/numeric_types_test_interface.h b/src/cobalt/bindings/testing/numeric_types_test_interface.h
index 6d752f5..713dea5 100644
--- a/src/cobalt/bindings/testing/numeric_types_test_interface.h
+++ b/src/cobalt/bindings/testing/numeric_types_test_interface.h
@@ -17,6 +17,8 @@
 #ifndef COBALT_BINDINGS_TESTING_NUMERIC_TYPES_TEST_INTERFACE_H_
 #define COBALT_BINDINGS_TESTING_NUMERIC_TYPES_TEST_INTERFACE_H_
 
+#include <limits>
+
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -56,6 +58,16 @@
   virtual uint32_t unsigned_long_property() { return 0; }
   virtual void set_unsigned_long_property(uint32_t value) {}
 
+  virtual int64_t LongLongReturnOperation() { return 0; }
+  virtual void LongLongArgumentOperation(int64_t value) {}
+  virtual int64_t long_long_property() { return 0; }
+  virtual void set_long_long_property(int64_t value) {}
+
+  virtual uint64_t UnsignedLongLongReturnOperation() { return 0; }
+  virtual void UnsignedLongLongArgumentOperation(uint64_t value) {}
+  virtual uint64_t unsigned_long_long_property() { return 0; }
+  virtual void set_unsigned_long_long_property(uint64_t value) {}
+
   virtual double DoubleReturnOperation() { return 0; }
   virtual void DoubleArgumentOperation(double value) {}
   virtual double double_property() { return 0; }
@@ -195,6 +207,53 @@
   static const char* min_value_string() { return "0"; }
 };
 
+#if defined(ENGINE_SUPPORTS_INT64)
+class LongLongTypeTest : public NumericTypesTestInterfaceT<int64_t> {
+ public:
+  int64_t LongLongReturnOperation() OVERRIDE {
+    return MockReturnValueOperation();
+  }
+  void LongLongArgumentOperation(int64_t value) OVERRIDE {
+    MockArgumentOperation(value);
+  }
+  int64_t long_long_property() OVERRIDE { return mock_get_property(); }
+  void set_long_long_property(int64_t value) OVERRIDE {
+    mock_set_property(value);
+  }
+
+  static const char* type_string() { return "longLong"; }
+  static int64_t max_value() { return 9223372036854775807ll; }
+  static int64_t min_value() { return -9223372036854775807ll - 1; }
+  // This is what 9223372036854775807 maps to in javascript.
+  static const char* max_value_string() { return "9223372036854776000"; }
+  static const char* min_value_string() { return "-9223372036854776000"; }
+};
+
+class UnsignedLongLongTypeTest : public NumericTypesTestInterfaceT<uint64_t> {
+ public:
+  uint64_t UnsignedLongLongReturnOperation() OVERRIDE {
+    return MockReturnValueOperation();
+  }
+  void UnsignedLongLongArgumentOperation(uint64_t value) OVERRIDE {
+    MockArgumentOperation(value);
+  }
+  uint64_t unsigned_long_long_property() OVERRIDE {
+    return mock_get_property();
+  }
+  void set_unsigned_long_long_property(uint64_t value) OVERRIDE {
+    mock_set_property(value);
+  }
+
+  static const char* type_string() { return "unsignedLongLong"; }
+
+  static uint64_t max_value() { return 18446744073709551615; }
+  static uint64_t min_value() { return 0; }
+  // This is what the value 18446744073709551615 maps to in javascript.
+  static const char* max_value_string() { return "18446744073709552000"; }
+  static const char* min_value_string() { return "0"; }
+};
+#endif  // ENGINE_SUPPORTS_INT64
+
 class DoubleTypeTest : public NumericTypesTestInterfaceT<double> {
  public:
   double DoubleReturnOperation() OVERRIDE { return MockReturnValueOperation(); }
diff --git a/src/cobalt/bindings/testing/object_type_bindings_test.cc b/src/cobalt/bindings/testing/object_type_bindings_test.cc
index 618dd5f..3747719 100644
--- a/src/cobalt/bindings/testing/object_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/object_type_bindings_test.cc
@@ -85,6 +85,7 @@
   EXPECT_STREQ("[object ArbitraryInterfacePrototype]", result.c_str());
 }
 
+#if defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT)
 TEST_F(PlatformObjectBindingsTest, PropertyIsOwnProperty) {
   EXPECT_CALL(test_mock(), arbitrary_object());
 
@@ -93,6 +94,18 @@
       "test.arbitraryObject.hasOwnProperty(\"arbitraryProperty\");", &result));
   EXPECT_STREQ("true", result.c_str());
 }
+#else
+TEST_F(PlatformObjectBindingsTest, PropertyIsDefinedOnPrototype) {
+  EXPECT_CALL(test_mock(), arbitrary_object());
+
+  std::string result;
+  EXPECT_TRUE(EvaluateScript(
+      "Object.getPrototypeOf(test.arbitraryObject).hasOwnProperty("
+      "\"arbitraryProperty\");",
+      &result));
+  EXPECT_STREQ("true", result.c_str());
+}
+#endif  // defined(ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT)
 
 TEST_F(PlatformObjectBindingsTest, MemberFunctionIsPrototypeProperty) {
   EXPECT_CALL(test_mock(), arbitrary_object()).Times(3);
diff --git a/src/cobalt/bindings/testing/operations_bindings_test.cc b/src/cobalt/bindings/testing/operations_bindings_test.cc
index a6f7288..a875c45 100644
--- a/src/cobalt/bindings/testing/operations_bindings_test.cc
+++ b/src/cobalt/bindings/testing/operations_bindings_test.cc
@@ -168,10 +168,17 @@
 }
 
 TEST_F(OperationsBindingsTest, StaticMethodNotPartOfOverloadSet) {
+  InSequence in_sequence_dummy;
+
   EXPECT_CALL(OperationsTestInterface::static_methods_mock.Get(),
               OverloadedFunction(_));
   EXPECT_TRUE(
       EvaluateScript("OperationsTestInterface.overloadedFunction(6.1);", NULL));
+
+  EXPECT_CALL(OperationsTestInterface::static_methods_mock.Get(),
+              OverloadedFunction(_, _));
+  EXPECT_TRUE(EvaluateScript(
+      "OperationsTestInterface.overloadedFunction(4, 8);", NULL));
 }
 
 TEST_F(OperationsBindingsTest, OverloadedOperationByOptionality) {
diff --git a/src/cobalt/bindings/testing/operations_test_interface.h b/src/cobalt/bindings/testing/operations_test_interface.h
index 7294491..05b4e7e 100644
--- a/src/cobalt/bindings/testing/operations_test_interface.h
+++ b/src/cobalt/bindings/testing/operations_test_interface.h
@@ -35,6 +35,7 @@
   class StaticMethodsMock {
    public:
     MOCK_METHOD1(OverloadedFunction, void(double));
+    MOCK_METHOD2(OverloadedFunction, void(double, double));
   };
 
   MOCK_METHOD0(VoidFunctionNoArgs, void());
@@ -73,6 +74,10 @@
     static_methods_mock.Get().OverloadedFunction(arg);
   }
 
+  static void OverloadedFunction(double arg1, double arg2) {
+    static_methods_mock.Get().OverloadedFunction(arg1, arg2);
+  }
+
   MOCK_METHOD1(OverloadedNullable, void(int32_t));
   MOCK_METHOD1(OverloadedNullable, void(base::optional<bool>));
 
diff --git a/src/cobalt/bindings/testing/put_forwards_interface.cc b/src/cobalt/bindings/testing/put_forwards_interface.cc
new file mode 100644
index 0000000..cfe82b1
--- /dev/null
+++ b/src/cobalt/bindings/testing/put_forwards_interface.cc
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/bindings/testing/put_forwards_interface.h"
+
+namespace cobalt {
+namespace bindings {
+namespace testing {
+
+base::LazyInstance<
+    ::testing::StrictMock<PutForwardsInterface::StaticMethodsMock> >
+    PutForwardsInterface::static_methods_mock = LAZY_INSTANCE_INITIALIZER;
+
+}  // namespace testing
+}  // namespace bindings
+}  // namespace cobalt
diff --git a/src/cobalt/bindings/testing/put_forwards_interface.h b/src/cobalt/bindings/testing/put_forwards_interface.h
index baa7b60..a91ef19 100644
--- a/src/cobalt/bindings/testing/put_forwards_interface.h
+++ b/src/cobalt/bindings/testing/put_forwards_interface.h
@@ -17,6 +17,7 @@
 #ifndef COBALT_BINDINGS_TESTING_PUT_FORWARDS_INTERFACE_H_
 #define COBALT_BINDINGS_TESTING_PUT_FORWARDS_INTERFACE_H_
 
+#include "base/lazy_instance.h"
 #include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -27,9 +28,22 @@
 
 class PutForwardsInterface : public script::Wrappable {
  public:
+  class StaticMethodsMock {
+   public:
+    MOCK_METHOD0(static_forwarding_attribute,
+                 scoped_refptr<ArbitraryInterface>(void));
+  };
+
   MOCK_METHOD0(forwarding_attribute, scoped_refptr<ArbitraryInterface>());
 
+  static scoped_refptr<ArbitraryInterface> static_forwarding_attribute() {
+    return static_methods_mock.Get().static_forwarding_attribute();
+  }
+
   DEFINE_WRAPPABLE_TYPE(PutForwardsInterface);
+
+  static base::LazyInstance< ::testing::StrictMock<StaticMethodsMock> >
+      static_methods_mock;
 };
 
 }  // namespace testing
diff --git a/src/cobalt/bindings/testing/put_forwards_test.cc b/src/cobalt/bindings/testing/put_forwards_test.cc
index ab7aa18..c9d1359 100644
--- a/src/cobalt/bindings/testing/put_forwards_test.cc
+++ b/src/cobalt/bindings/testing/put_forwards_test.cc
@@ -43,6 +43,17 @@
   EXPECT_TRUE(EvaluateScript("test.forwardingAttribute = 'apple';", NULL));
 }
 
+TEST_F(PutForwardsTest, StaticForwardsToInterface) {
+  scoped_refptr<StrictMock<ArbitraryInterface> > arbitrary_interface_mock(
+      new StrictMock<ArbitraryInterface>());
+  EXPECT_CALL(PutForwardsInterface::static_methods_mock.Get(),
+              static_forwarding_attribute())
+      .WillOnce(Return(arbitrary_interface_mock));
+  EXPECT_CALL(*arbitrary_interface_mock, set_arbitrary_property("orange"));
+  EXPECT_TRUE(EvaluateScript(
+      "PutForwardsInterface.staticForwardingAttribute = 'orange';", NULL));
+}
+
 TEST_F(NestedPutForwardsTest, ForwardsToNestedInterface) {
   scoped_refptr<StrictMock<PutForwardsInterface> > puts_forward_interface_mock(
       new StrictMock<PutForwardsInterface>());
diff --git a/src/cobalt/bindings/testing/static_properties_bindings_test.cc b/src/cobalt/bindings/testing/static_properties_bindings_test.cc
index ae66885..51fe181 100644
--- a/src/cobalt/bindings/testing/static_properties_bindings_test.cc
+++ b/src/cobalt/bindings/testing/static_properties_bindings_test.cc
@@ -19,6 +19,9 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::_;
+using ::testing::A;
+using ::testing::InSequence;
 using ::testing::Return;
 
 namespace cobalt {
@@ -38,6 +41,43 @@
       EvaluateScript("StaticPropertiesInterface.staticFunction();", NULL));
 }
 
+TEST_F(StaticPropertiesBindingsTest,
+       StaticOverloadedOperationByNumberOfArguments) {
+  InSequence in_sequence_dummy;
+
+  EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
+              StaticFunction());
+  EXPECT_TRUE(
+      EvaluateScript("StaticPropertiesInterface.staticFunction();", NULL));
+
+  EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
+              StaticFunction(_, _, A<int32_t>()));
+  EXPECT_TRUE(EvaluateScript(
+      "StaticPropertiesInterface.staticFunction(6, 8, 9);", NULL));
+
+  EXPECT_CALL(
+      StaticPropertiesInterface::static_methods_mock.Get(),
+      StaticFunction(_, _, A<const scoped_refptr<ArbitraryInterface>&>()));
+  EXPECT_TRUE(
+      EvaluateScript("StaticPropertiesInterface.staticFunction(6, 8, new "
+                     "ArbitraryInterface());",
+                     NULL));
+}
+
+TEST_F(StaticPropertiesBindingsTest, StaticOverloadedOperationByType) {
+  InSequence in_sequence_dummy;
+
+  EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
+              StaticFunction(A<int32_t>()));
+  EXPECT_TRUE(
+      EvaluateScript("StaticPropertiesInterface.staticFunction(4);", NULL));
+
+  EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
+              StaticFunction(A<const std::string&>()));
+  EXPECT_TRUE(EvaluateScript(
+      "StaticPropertiesInterface.staticFunction(\"foo\");", NULL));
+}
+
 TEST_F(StaticPropertiesBindingsTest, GetStaticAttribute) {
   std::string result;
   EXPECT_CALL(StaticPropertiesInterface::static_methods_mock.Get(),
diff --git a/src/cobalt/bindings/testing/static_properties_interface.h b/src/cobalt/bindings/testing/static_properties_interface.h
index 2c67a48..5abd47a 100644
--- a/src/cobalt/bindings/testing/static_properties_interface.h
+++ b/src/cobalt/bindings/testing/static_properties_interface.h
@@ -17,7 +17,10 @@
 #ifndef COBALT_BINDINGS_TESTING_STATIC_PROPERTIES_INTERFACE_H_
 #define COBALT_BINDINGS_TESTING_STATIC_PROPERTIES_INTERFACE_H_
 
+#include <string>
+
 #include "base/lazy_instance.h"
+#include "cobalt/bindings/testing/arbitrary_interface.h"
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -30,10 +33,30 @@
   class StaticMethodsMock {
    public:
     MOCK_METHOD0(StaticFunction, void());
+    MOCK_METHOD1(StaticFunction, void(int32_t));
+    MOCK_METHOD1(StaticFunction, void(const std::string&));
+    MOCK_METHOD3(StaticFunction, void(int32_t, int32_t, int32_t));
+    MOCK_METHOD3(StaticFunction,
+                 void(int32_t, int32_t,
+                      const scoped_refptr<ArbitraryInterface>&));
     MOCK_METHOD0(static_attribute, std::string());
     MOCK_METHOD1(set_static_attribute, void(const std::string&));
   };
+
   static void StaticFunction() { static_methods_mock.Get().StaticFunction(); }
+  static void StaticFunction(int32_t arg) {
+    static_methods_mock.Get().StaticFunction(arg);
+  }
+  static void StaticFunction(const std::string& arg) {
+    static_methods_mock.Get().StaticFunction(arg);
+  }
+  static void StaticFunction(int32_t arg1, int32_t arg2, int32_t arg3) {
+    static_methods_mock.Get().StaticFunction(arg1, arg2, arg3);
+  }
+  static void StaticFunction(int32_t arg1, int32_t arg2,
+                             const scoped_refptr<ArbitraryInterface>& arg3) {
+    static_methods_mock.Get().StaticFunction(arg1, arg2, arg3);
+  }
   static std::string static_attribute() {
     return static_methods_mock.Get().static_attribute();
   }
diff --git a/src/cobalt/bindings/testing/testing.gyp b/src/cobalt/bindings/testing/testing.gyp
index 3f1e0c2..49c20e4 100644
--- a/src/cobalt/bindings/testing/testing.gyp
+++ b/src/cobalt/bindings/testing/testing.gyp
@@ -104,6 +104,7 @@
         'exceptions_interface.cc',
         'named_constructor_interface.cc',
         'operations_test_interface.cc',
+        'put_forwards_interface.cc',
         'static_properties_interface.cc',
       ],
       'defines': [ '<@(bindings_defines)'],
@@ -165,7 +166,7 @@
       'variables': {
         'executable_name': 'bindings_test',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
 
     {
@@ -192,7 +193,7 @@
       'variables': {
         'executable_name': 'bindings_sandbox',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/bindings/testing/union_type_bindings_test.cc b/src/cobalt/bindings/testing/union_type_bindings_test.cc
index 559678d..e4593a2 100644
--- a/src/cobalt/bindings/testing/union_type_bindings_test.cc
+++ b/src/cobalt/bindings/testing/union_type_bindings_test.cc
@@ -94,6 +94,47 @@
   EXPECT_TRUE(union_type.AsType<scoped_refptr<ArbitraryInterface> >());
 }
 
+TEST_F(UnionTypesBindingsTest, ConvertFromJSInvalid) {
+  InSequence dummy;
+
+  UnionTypesInterface::UnionBasePropertyType union_base_type;
+  // Try to assign wrong interface type.
+  // First assign a valid value.
+  EXPECT_CALL(test_mock(), set_union_base_property(_))
+      .WillOnce(SaveArg<0>(&union_base_type));
+  EXPECT_TRUE(
+      EvaluateScript("test.unionBaseProperty = \"string type\";", NULL));
+  ASSERT_TRUE(union_base_type.IsType<std::string>());
+  EXPECT_EQ("string type", union_base_type.AsType<std::string>());
+  // Attempt to assign invalid value.
+  EXPECT_FALSE(EvaluateScript(
+      "test.unionBaseProperty = new EnumerationInterface();", NULL));
+  // Check the original value was preserved.
+  ASSERT_TRUE(union_base_type.IsType<std::string>());
+  EXPECT_EQ("string type", union_base_type.AsType<std::string>());
+}
+
+TEST_F(UnionTypesBindingsTest, ConvertFromJSInherit) {
+  InSequence dummy;
+
+  UnionTypesInterface::UnionBasePropertyType union_base_type;
+  // Assign with base.
+  EXPECT_CALL(test_mock(), set_union_base_property(_))
+      .WillOnce(SaveArg<0>(&union_base_type));
+  EXPECT_TRUE(
+      EvaluateScript("test.unionBaseProperty = new BaseInterface();", NULL));
+  ASSERT_TRUE(union_base_type.IsType<scoped_refptr<BaseInterface> >());
+  EXPECT_TRUE(union_base_type.AsType<scoped_refptr<BaseInterface> >());
+
+  // Assign with derived.
+  EXPECT_CALL(test_mock(), set_union_base_property(_))
+      .WillOnce(SaveArg<0>(&union_base_type));
+  EXPECT_TRUE(
+      EvaluateScript("test.unionBaseProperty = new DerivedInterface();", NULL));
+  ASSERT_TRUE(union_base_type.IsType<scoped_refptr<BaseInterface> >());
+  EXPECT_TRUE(union_base_type.AsType<scoped_refptr<BaseInterface> >());
+}
+
 TEST_F(UnionTypesBindingsTest, SetNullableUnion) {
   InSequence dummy;
 
diff --git a/src/cobalt/bindings/testing/union_types_interface.h b/src/cobalt/bindings/testing/union_types_interface.h
index c631d36..7d0f7c1 100644
--- a/src/cobalt/bindings/testing/union_types_interface.h
+++ b/src/cobalt/bindings/testing/union_types_interface.h
@@ -17,7 +17,10 @@
 #ifndef COBALT_BINDINGS_TESTING_UNION_TYPES_INTERFACE_H_
 #define COBALT_BINDINGS_TESTING_UNION_TYPES_INTERFACE_H_
 
+#include <string>
+
 #include "cobalt/bindings/testing/arbitrary_interface.h"
+#include "cobalt/bindings/testing/base_interface.h"
 #include "cobalt/script/union_type.h"
 #include "cobalt/script/wrappable.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -33,6 +36,9 @@
                              int32_t> UnionPropertyType;
   typedef base::optional<script::UnionType2<double, std::string> >
       NullableUnionPropertyType;
+  typedef script::UnionType2<scoped_refptr<BaseInterface>, std::string>
+      UnionBasePropertyType;
+
   MOCK_METHOD0(union_property, UnionPropertyType());
   MOCK_METHOD1(set_union_property, void(const UnionPropertyType&));
 
@@ -45,6 +51,9 @@
   MOCK_METHOD1(set_nullable_union_property,
                void(const NullableUnionPropertyType&));
 
+  MOCK_METHOD0(union_base_property, UnionBasePropertyType());
+  MOCK_METHOD1(set_union_base_property, void(const UnionBasePropertyType&));
+
   DEFINE_WRAPPABLE_TYPE(UnionTypesInterface);
 };
 
diff --git a/src/cobalt/browser/application.cc b/src/cobalt/browser/application.cc
index 41ae68b..5ec73ec 100644
--- a/src/cobalt/browser/application.cc
+++ b/src/cobalt/browser/application.cc
@@ -165,6 +165,31 @@
     loader::image::ImageDecoder::UseStubImageDecoder();
   }
 }
+
+void SetIntegerIfSwitchIsSet(const char* switch_name, int* output) {
+  if (CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) {
+    int32 out;
+    if (base::StringToInt32(
+            CommandLine::ForCurrentProcess()->GetSwitchValueNative(switch_name),
+            &out)) {
+      LOG(INFO) << "Command line switch '" << switch_name << "': Modifying "
+                << *output << " -> " << out;
+      *output = out;
+    } else {
+      LOG(ERROR) << "Invalid value for command line setting: " << switch_name;
+    }
+  }
+}
+
+void ApplyCommandLineSettingsToRendererOptions(
+    renderer::RendererModule::Options* options) {
+  SetIntegerIfSwitchIsSet(browser::switches::kSurfaceCacheSizeInBytes,
+                          &options->surface_cache_size_in_bytes);
+  SetIntegerIfSwitchIsSet(browser::switches::kScratchSurfaceCacheSizeInBytes,
+                          &options->scratch_surface_cache_size_in_bytes);
+  SetIntegerIfSwitchIsSet(browser::switches::kSkiaCacheSizeInBytes,
+                          &options->skia_cache_size_in_bytes);
+}
 #endif  // ENABLE_COMMAND_LINE_SWITCHES
 
 // Restrict navigation to a couple of whitelisted URLs by default.
@@ -264,6 +289,8 @@
   options.network_module_options.preferred_language = language;
 
 #if defined(ENABLE_COMMAND_LINE_SWITCHES)
+  ApplyCommandLineSettingsToRendererOptions(&options.renderer_module_options);
+
   if (CommandLine::ForCurrentProcess()->HasSwitch(
           browser::switches::kNullSavegame)) {
     options.storage_manager_options.savegame_options.factory =
@@ -499,19 +526,25 @@
   if (app_event->type() == system_window::ApplicationEvent::kQuit) {
     DLOG(INFO) << "Got quit event.";
     app_status_ = kWillQuitAppStatus;
+#if !defined(OS_STARBOARD)
     browser_module_->SetWillQuit();
     browser_module_->SetPaused(false);
+#endif  // !defined(OS_STARBOARD)
     Quit();
   } else if (app_event->type() == system_window::ApplicationEvent::kSuspend) {
     DLOG(INFO) << "Got suspend event.";
     app_status_ = kPausedAppStatus;
     ++app_suspend_count_;
+#if !defined(OS_STARBOARD)
     browser_module_->SetPaused(true);
+#endif  // !defined(OS_STARBOARD)
   } else if (app_event->type() == system_window::ApplicationEvent::kResume) {
     DLOG(INFO) << "Got resume event.";
     app_status_ = kRunningAppStatus;
     ++app_resume_count_;
+#if !defined(OS_STARBOARD)
     browser_module_->SetPaused(false);
+#endif  // !defined(OS_STARBOARD)
   }
 }
 
diff --git a/src/cobalt/browser/browser_bindings.gyp b/src/cobalt/browser/browser_bindings.gyp
index 2892de9..45d7061 100644
--- a/src/cobalt/browser/browser_bindings.gyp
+++ b/src/cobalt/browser/browser_bindings.gyp
@@ -21,6 +21,10 @@
     # be generated.
     'bindings_output_dir': '<(SHARED_INTERMEDIATE_DIR)/bindings/browser',
 
+    'bindings_dependencies': [
+      '../h5vcc/h5vcc.gyp:h5vcc',
+    ],
+
     # Bindings for the interfaces in this list will be generated, and there must
     # be an implementation declared in a header that lives in the same
     # directory of each IDL.
@@ -144,6 +148,7 @@
         '../h5vcc/dial/DialServer.idl',
         '../h5vcc/H5vcc.idl',
         '../h5vcc/H5vccAccountInfo.idl',
+        '../h5vcc/H5vccAccountManager.idl',
         '../h5vcc/H5vccAudioConfig.idl',
         '../h5vcc/H5vccAudioConfigArray.idl',
         '../h5vcc/H5vccCVal.idl',
diff --git a/src/cobalt/browser/cobalt.gyp b/src/cobalt/browser/cobalt.gyp
index 46bad3a..4f73099 100644
--- a/src/cobalt/browser/cobalt.gyp
+++ b/src/cobalt/browser/cobalt.gyp
@@ -57,7 +57,7 @@
       'variables': {
         'executable_name': 'cobalt',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
     {
       'target_name': 'snapshot_app_stats',
@@ -90,7 +90,7 @@
       'variables': {
         'executable_name': 'snapshot_app_stats',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
   ],
diff --git a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
index cf004c2..b9f074d 100644
--- a/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
+++ b/src/cobalt/browser/global_constructors_idls_idl_files_list.tmp
@@ -113,6 +113,7 @@
 ../h5vcc/dial/DialServer.idl
 ../h5vcc/H5vcc.idl
 ../h5vcc/H5vccAccountInfo.idl
+../h5vcc/H5vccAccountManager.idl
 ../h5vcc/H5vccAudioConfig.idl
 ../h5vcc/H5vccAudioConfigArray.idl
 ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/global_objects_idl_files_list.tmp b/src/cobalt/browser/global_objects_idl_files_list.tmp
index cf004c2..b9f074d 100644
--- a/src/cobalt/browser/global_objects_idl_files_list.tmp
+++ b/src/cobalt/browser/global_objects_idl_files_list.tmp
@@ -113,6 +113,7 @@
 ../h5vcc/dial/DialServer.idl
 ../h5vcc/H5vcc.idl
 ../h5vcc/H5vccAccountInfo.idl
+../h5vcc/H5vccAccountManager.idl
 ../h5vcc/H5vccAudioConfig.idl
 ../h5vcc/H5vccAudioConfigArray.idl
 ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/h5vcc_url_handler.cc b/src/cobalt/browser/h5vcc_url_handler.cc
index d15a55e..18ba0c6 100644
--- a/src/cobalt/browser/h5vcc_url_handler.cc
+++ b/src/cobalt/browser/h5vcc_url_handler.cc
@@ -19,7 +19,6 @@
 #include <string>
 
 #include "base/bind.h"
-#include "cobalt/base/localized_strings.h"
 #include "cobalt/browser/browser_module.h"
 
 namespace cobalt {
@@ -78,15 +77,6 @@
 const char kAgeRestricted[] = "age-restricted";
 
 const char kRetryParam[] = "retry-url";
-
-const char kNetworkFailureMessageId[] = "UNABLE_TO_CONTACT_YOUTUBE";
-const char kNetworkFailureMessageFallback[] = "Unable to contact YouTube";
-const char kSignedOutMessageId[] = "OFFLINE_MESSAGE_1";
-const char kSignedOutMessageFallback[] =
-    "You are signed out of PSN. To use YouTube, you need to sign in to PSN.";
-const char kAgeRestrictedMessageId[] = "AGE_RESTRICTED";
-const char kAgeRestrictedMessageFallback[] =
-    "YouTube is not intended for use by children under 13.";
 }  // namespace
 
 H5vccURLHandler::H5vccURLHandler(BrowserModule* browser_module,
@@ -118,9 +108,8 @@
 
 bool H5vccURLHandler::HandleNetworkFailure() {
   system_window::SystemWindow::DialogOptions dialog_options;
-  dialog_options.message = base::LocalizedStrings::GetInstance()->GetString(
-      kNetworkFailureMessageId, kNetworkFailureMessageFallback);
-  dialog_options.num_buttons = 1;
+  dialog_options.message_code =
+      system_window::SystemWindow::kDialogConnectionError;
   dialog_options.callback = base::Bind(
       &H5vccURLHandler::OnNetworkFailureDialogResponse, base::Unretained(this));
   system_window_->ShowDialog(dialog_options);
@@ -129,9 +118,8 @@
 
 bool H5vccURLHandler::HandleSignedOut() {
   system_window::SystemWindow::DialogOptions dialog_options;
-  dialog_options.message = base::LocalizedStrings::GetInstance()->GetString(
-      kSignedOutMessageId, kSignedOutMessageFallback);
-  dialog_options.num_buttons = 1;
+  dialog_options.message_code =
+      system_window::SystemWindow::kDialogUserSignedOut;
   dialog_options.callback = base::Bind(
       &H5vccURLHandler::OnSignedOutDialogResponse, base::Unretained(this));
   system_window_->ShowDialog(dialog_options);
@@ -140,9 +128,8 @@
 
 bool H5vccURLHandler::HandleAgeRestricted() {
   system_window::SystemWindow::DialogOptions dialog_options;
-  dialog_options.message = base::LocalizedStrings::GetInstance()->GetString(
-      kAgeRestrictedMessageId, kAgeRestrictedMessageFallback);
-  dialog_options.num_buttons = 0;
+  dialog_options.message_code =
+      system_window::SystemWindow::kDialogUserAgeRestricted;
   system_window_->ShowDialog(dialog_options);
   return true;
 }
diff --git a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
index 2c03040..86c81b6 100644
--- a/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
+++ b/src/cobalt/browser/interfaces_info_individual_static_idl_files_list.tmp
@@ -113,6 +113,7 @@
 ../h5vcc/dial/DialServer.idl
 ../h5vcc/H5vcc.idl
 ../h5vcc/H5vccAccountInfo.idl
+../h5vcc/H5vccAccountManager.idl
 ../h5vcc/H5vccAudioConfig.idl
 ../h5vcc/H5vccAudioConfigArray.idl
 ../h5vcc/H5vccCVal.idl
diff --git a/src/cobalt/browser/main.cc b/src/cobalt/browser/main.cc
index 9f25b03..ef98aff 100644
--- a/src/cobalt/browser/main.cc
+++ b/src/cobalt/browser/main.cc
@@ -19,6 +19,7 @@
 #include "cobalt/base/wrap_main.h"
 #include "cobalt/browser/application.h"
 #if defined(OS_STARBOARD)
+#include "cobalt/browser/starboard/event_handler.h"
 #include "cobalt/system_window/starboard/system_window.h"
 #endif
 
@@ -43,7 +44,7 @@
 
 #if defined(OS_STARBOARD)
 COBALT_WRAP_EVENT_MAIN(StartApplication,
-                       cobalt::system_window::HandleInputEvent,
+                       cobalt::browser::EventHandler::HandleEvent,
                        StopApplication);
 #else
 COBALT_WRAP_BASE_MAIN(StartApplication, StopApplication);
diff --git a/src/cobalt/browser/starboard/application.cc b/src/cobalt/browser/starboard/application.cc
index dc50b6f..97bd985 100644
--- a/src/cobalt/browser/starboard/application.cc
+++ b/src/cobalt/browser/starboard/application.cc
@@ -16,6 +16,8 @@
 
 #include "cobalt/browser/application.h"
 
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/browser/starboard/event_handler.h"
 #include "starboard/system.h"
 
 namespace cobalt {
@@ -24,8 +26,13 @@
 class ApplicationStarboard : public Application {
  public:
   explicit ApplicationStarboard(const base::Closure& quit_closure)
-      : Application(quit_closure) {}
+      : Application(quit_closure), event_handler_(&event_dispatcher_) {}
   ~ApplicationStarboard() OVERRIDE {}
+
+ private:
+  // Event handler to receive Starboard events, convert to Cobalt events
+  // and dispatch to the rest of the system.
+  EventHandler event_handler_;
 };
 
 scoped_ptr<Application> CreateApplication(const base::Closure& quit_closure) {
diff --git a/src/cobalt/browser/starboard/event_handler.cc b/src/cobalt/browser/starboard/event_handler.cc
new file mode 100644
index 0000000..4ef7069
--- /dev/null
+++ b/src/cobalt/browser/starboard/event_handler.cc
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/browser/starboard/event_handler.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "cobalt/system_window/application_event.h"
+#include "cobalt/system_window/starboard/system_window.h"
+
+namespace cobalt {
+namespace browser {
+
+namespace {
+EventHandler* g_the_event_handler = NULL;
+}  // namespace
+
+EventHandler::EventHandler(base::EventDispatcher* event_dispatcher)
+    : event_dispatcher_(event_dispatcher) {
+  DCHECK(!g_the_event_handler) << "There should be only one event handler.";
+  g_the_event_handler = this;
+}
+
+// static
+void EventHandler::HandleEvent(const SbEvent* starboard_event) {
+  DCHECK(starboard_event);
+
+  // Forward input events to |SystemWindow|.
+  if (starboard_event->type == kSbEventTypeInput) {
+    system_window::HandleInputEvent(starboard_event);
+    return;
+  }
+
+  // Handle all other events internally.
+  DCHECK(g_the_event_handler);
+  g_the_event_handler->DispatchEvent(starboard_event);
+}
+
+void EventHandler::DispatchEvent(const SbEvent* starboard_event) const {
+  // Create a Cobalt event from the Starboard event, if recognized.
+  scoped_ptr<base::Event> cobalt_event;
+  if (starboard_event->type == kSbEventTypeResume) {
+    cobalt_event.reset(new system_window::ApplicationEvent(
+        system_window::ApplicationEvent::kResume));
+  } else if (starboard_event->type == kSbEventTypeSuspend) {
+    cobalt_event.reset(new system_window::ApplicationEvent(
+        system_window::ApplicationEvent::kSuspend));
+  }
+
+  // Dispatch the Cobalt event, if created.
+  if (cobalt_event) {
+    event_dispatcher_->DispatchEvent(cobalt_event.Pass());
+  } else {
+    DLOG(WARNING) << "Unhandled Starboard event of type: "
+                  << starboard_event->type;
+  }
+}
+
+}  // namespace browser
+}  // namespace cobalt
diff --git a/src/cobalt/browser/starboard/event_handler.h b/src/cobalt/browser/starboard/event_handler.h
new file mode 100644
index 0000000..ed11064
--- /dev/null
+++ b/src/cobalt/browser/starboard/event_handler.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
+#define COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
+
+#include "cobalt/base/event_dispatcher.h"
+#include "starboard/event.h"
+
+namespace cobalt {
+namespace browser {
+
+class EventHandler {
+ public:
+  explicit EventHandler(base::EventDispatcher* event_dispatcher);
+
+  // Static event handler called by |SbEventHandle|. Forwards input events to
+  // |system_window::HandleInputEvent| and passes all other events to
+  // |DispatchEvent|.
+  static void HandleEvent(const SbEvent* event);
+
+ private:
+  // Creates a Cobalt event from a Starboard event and dispatches to the rest
+  // of the system via |event_dispatcher_|.
+  void DispatchEvent(const SbEvent* event) const;
+
+  // The event dispatcher that dispatches Cobalt events to the rest of the
+  // system.
+  base::EventDispatcher* event_dispatcher_;
+};
+
+}  // namespace browser
+}  // namespace cobalt
+
+#endif  // COBALT_BROWSER_STARBOARD_EVENT_HANDLER_H_
diff --git a/src/cobalt/browser/starboard/platform_browser.gyp b/src/cobalt/browser/starboard/platform_browser.gyp
index cd002f7..a9ae70f 100644
--- a/src/cobalt/browser/starboard/platform_browser.gyp
+++ b/src/cobalt/browser/starboard/platform_browser.gyp
@@ -19,6 +19,8 @@
       'type': 'static_library',
       'sources': [
         'application.cc',
+        'event_handler.cc',
+        'event_handler.h',
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/browser/browser.gyp:browser',
diff --git a/src/cobalt/browser/switches.cc b/src/cobalt/browser/switches.cc
index e53e617..9258a4f 100644
--- a/src/cobalt/browser/switches.cc
+++ b/src/cobalt/browser/switches.cc
@@ -71,13 +71,32 @@
 // Creates a remote debugging server and listens on the specified port.
 const char kRemoteDebuggingPort[] = "remote_debugging_port";
 
+// Determines the capacity of the scratch surface cache.  The scratch surface
+// cache facilitates the reuse of temporary offscreen surfaces within a single
+// frame.  This setting is only relevant when using the hardware-accelerated
+// Skia rasterizer.
+const char kScratchSurfaceCacheSizeInBytes[] =
+    "scratch_surface_cache_size_in_bytes";
+
 // If this flag is set, Cobalt will automatically shutdown after the specified
 // number of seconds have passed.
 const char kShutdownAfter[] = "shutdown_after";
 
+// Determines the capacity of the skia cache.  The Skia cache is maintained
+// within Skia and is used to cache the results of complicated effects such as
+// shadows, so that Skia draw calls that are used repeatedly across frames can
+// be cached into surfaces.  This setting is only relevant when using the
+// hardware-accelerated Skia rasterizer.
+const char kSkiaCacheSizeInBytes[] = "skia_cache_size_in_bytes";
+
 // Decode all images using StubImageDecoder.
 const char kStubImageDecoder[] = "stub_image_decoder";
 
+// Determines the capacity of the surface cache.  The surface cache tracks which
+// render tree nodes are being re-used across frames and stores the nodes that
+// are most CPU-expensive to render into surfaces.
+const char kSurfaceCacheSizeInBytes[] = "surface_cache_size_in_bytes";
+
 // If this is set, then a trace (see base/debug/trace_eventh.h) is started on
 // Cobalt startup.  A value must also be specified for this switch, which is
 // the duration in seconds of how long the trace will be done for before ending
diff --git a/src/cobalt/browser/switches.h b/src/cobalt/browser/switches.h
index 0a29c37..4c66e0c 100644
--- a/src/cobalt/browser/switches.h
+++ b/src/cobalt/browser/switches.h
@@ -42,6 +42,9 @@
 extern const char kViewport[];
 extern const char kVideoDecoderStub[];
 extern const char kWebDriverPort[];
+extern const char kSurfaceCacheSizeInBytes[];
+extern const char kScratchSurfaceCacheSizeInBytes[];
+extern const char kSkiaCacheSizeInBytes[];
 #endif  // ENABLE_COMMAND_LINE_SWITCHES
 
 }  // namespace switches
diff --git a/src/cobalt/browser/web_module.cc b/src/cobalt/browser/web_module.cc
index b3741c4..88b5286 100644
--- a/src/cobalt/browser/web_module.cc
+++ b/src/cobalt/browser/web_module.cc
@@ -525,21 +525,6 @@
       network_module, window_dimensions, resource_provider, layout_refresh_rate,
       options);
 
-#if defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
-  CommandLine* command_line = CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(browser::switches::kPartialLayout)) {
-    const std::string partial_layout_string =
-        command_line->GetSwitchValueASCII(browser::switches::kPartialLayout);
-    OnPartialLayoutConsoleCommandReceived(partial_layout_string);
-  }
-  partial_layout_command_handler_.reset(
-      new base::ConsoleCommandManager::CommandHandler(
-          browser::switches::kPartialLayout,
-          base::Bind(&WebModule::OnPartialLayoutConsoleCommandReceived,
-                     base::Unretained(this)),
-          kPartialLayoutCommandShortHelp, kPartialLayoutCommandLongHelp));
-#endif  // defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
-
   // Start the dedicated thread and create the internal implementation
   // object on that thread.
 #if defined(ADDRESS_SANITIZER)
@@ -567,6 +552,21 @@
                            base::Bind(&base::WaitableEvent::Signal,
                                       base::Unretained(&is_initialized)));
   is_initialized.Wait();
+
+#if defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
+  CommandLine* command_line = CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(browser::switches::kPartialLayout)) {
+    const std::string partial_layout_string =
+        command_line->GetSwitchValueASCII(browser::switches::kPartialLayout);
+    OnPartialLayoutConsoleCommandReceived(partial_layout_string);
+  }
+  partial_layout_command_handler_.reset(
+      new base::ConsoleCommandManager::CommandHandler(
+          browser::switches::kPartialLayout,
+          base::Bind(&WebModule::OnPartialLayoutConsoleCommandReceived,
+                     base::Unretained(this)),
+          kPartialLayoutCommandShortHelp, kPartialLayoutCommandLongHelp));
+#endif  // defined(ENABLE_PARTIAL_LAYOUT_CONTROL)
 }
 
 WebModule::~WebModule() {
diff --git a/src/cobalt/build/build.id b/src/cobalt/build/build.id
index 3acfe13..4db8c83 100644
--- a/src/cobalt/build/build.id
+++ b/src/cobalt/build/build.id
@@ -1 +1 @@
-8885
\ No newline at end of file
+9617
\ No newline at end of file
diff --git a/src/cobalt/build/config/base.gypi b/src/cobalt/build/config/base.gypi
index fd0ee92..ae3ac78 100644
--- a/src/cobalt/build/config/base.gypi
+++ b/src/cobalt/build/config/base.gypi
@@ -67,6 +67,9 @@
     # Set to 1 to build with DIAL support.
     'in_app_dial%': 0,
 
+    # Set to 1 to enable H5vccAccountManager.
+    'enable_account_manager%': 0,
+
     # Set to 1 to compile with SPDY support.
     'enable_spdy%': 0,
 
@@ -103,6 +106,24 @@
     #   "cobalt/renderer/egl_and_gles/egl_and_gles_<gl_type>.gyp not found"
     'gl_type%': 'system_gles2',
 
+    # Determines the capacity of the skia cache.  The Skia cache is maintained
+    # within Skia and is used to cache the results of complicated effects such
+    # as shadows, so that Skia draw calls that are used repeatedly across
+    # frames can be cached into surfaces.  This setting is only relevant when
+    # using the hardware-accelerated Skia rasterizer.
+    'skia_cache_size_in_bytes%': 4 * 1024 * 1024,
+
+    # Determines the capacity of the scratch surface cache.  The scratch
+    # surface cache facilitates the reuse of temporary offscreen surfaces
+    # within a single frame.  This setting is only relevant when using the
+    # hardware-accelerated Skia rasterizer.
+    'scratch_surface_cache_size_in_bytes%': 7 * 1024 * 1024,
+
+    # Determines the capacity of the surface cache.  The surface cache tracks
+    # which render tree nodes are being re-used across frames and stores the
+    # nodes that are most CPU-expensive to render into surfaces.
+    'surface_cache_size_in_bytes%': 0,
+
     # Compiler configuration.
 
     # The following variables are used to specify compiler and linker
@@ -249,7 +270,7 @@
         'defines': [
           'COBALT_DISABLE_SPDY',
         ],
-      }]
+      }],
     ],
 
     # TODO: Revisit and remove unused configurations.
diff --git a/src/cobalt/build/config/base.py b/src/cobalt/build/config/base.py
index 8e4a62f..4c46c70 100644
--- a/src/cobalt/build/config/base.py
+++ b/src/cobalt/build/config/base.py
@@ -23,8 +23,15 @@
 import gyp_utils
 
 
+class Configs(object):
+  """Strings representing valid build configurations."""
+  DEBUG = 'debug'
+  DEVEL = 'devel'
+  GOLD = 'gold'
+  QA = 'qa'
+
 # Represents all valid build configurations.
-VALID_BUILD_CONFIGS = ['debug', 'devel', 'qa', 'gold']
+VALID_BUILD_CONFIGS = [Configs.DEBUG, Configs.DEVEL, Configs.QA, Configs.GOLD]
 
 
 # Represents all supported platforms, uniquified and sorted.
diff --git a/src/cobalt/build/copy_data.py b/src/cobalt/build/copy_data.py
deleted file mode 100755
index cd1d6a2..0000000
--- a/src/cobalt/build/copy_data.py
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/usr/bin/python
-# Copyright 2014 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file is based on build/copy_test_data_ios.py
-
-"""Copies data files or directories into a given output directory.
-
-Since the output of this script is intended to be use by GYP, all resulting
-paths are using Unix-style forward flashes.
-"""
-
-import argparse
-import os
-import posixpath
-import shutil
-import sys
-if os.name == 'nt':
-  import win32api
-
-
-class WrongNumberOfArgumentsException(Exception):
-  pass
-
-
-def EscapePath(path):
-  """Returns a path with spaces escaped."""
-  return path.replace(' ', '\\ ')
-
-
-def ListFilesForPath(path):
-  """Returns a list of all the files under a given path."""
-  output = []
-  # Ignore revision control metadata directories.
-  if (os.path.basename(path).startswith('.git') or
-      os.path.basename(path).startswith('.svn')):
-    return output
-
-  # Files get returned without modification.
-  if not os.path.isdir(path):
-    output.append(path)
-    return output
-
-  # Directories get recursively expanded.
-  contents = os.listdir(path)
-  for item in contents:
-    full_path = posixpath.join(path, item)
-    output.extend(ListFilesForPath(full_path))
-  return output
-
-
-def CalcInputs(inputs):
-  """Computes the full list of input files. The output is a list of
-  (filepath, filepath relative to input dir)"""
-  # |inputs| is a list of paths, which may be directories.
-  output = []
-  for input_file in inputs:
-    file_list = ListFilesForPath(input_file)
-    dirname = posixpath.dirname(input_file)
-    output.extend([(x, posixpath.relpath(x, dirname)) for x in file_list])
-  return output
-
-
-def CopyFiles(files_to_copy, output_basedir):
-  """Copies files to the given output directory."""
-  for (filename, relative_filename) in files_to_copy:
-    if os.name == 'nt':
-      # Some of the files (especially for layout tests) result in very long
-      # paths (especially on build machines) such that shutil.copy fails.
-      filename = win32api.GetShortPathName(filename)
-      output_basedir = win32api.GetShortPathName(output_basedir)
-    output_filename = posixpath.join(output_basedir, relative_filename)
-    output_dir = posixpath.dirname(output_filename)
-
-    # In cases where a directory has turned into a file or vice versa, delete it
-    # before copying it below.
-    if os.path.exists(output_dir) and not os.path.isdir(output_dir):
-      os.remove(output_dir)
-    if os.path.exists(output_filename) and os.path.isdir(output_filename):
-      shutil.rmtree(output_filename)
-
-    if not os.path.exists(output_dir):
-      os.makedirs(output_dir)
-    shutil.copy(filename, output_filename)
-
-
-def DoMain(argv):
-  """Called by GYP using pymod_do_main."""
-  parser = argparse.ArgumentParser()
-  parser.add_argument('-o', dest='output_dir', help='output directory')
-  parser.add_argument('--inputs', action='store_true', dest='list_inputs',
-                      help='prints a list of all input files')
-  parser.add_argument('--outputs', action='store_true', dest='list_outputs',
-                      help='prints a list of all output files')
-  parser.add_argument('input_paths', metavar='path', nargs='+',
-                      help='path to an input file or directory')
-  options = parser.parse_args(argv)
-
-  escaped_files = [EscapePath(x) for x in options.input_paths]
-  files_to_copy = CalcInputs(escaped_files)
-  if options.list_inputs:
-    return '\n'.join([x[0] for x in files_to_copy])
-
-  if not options.output_dir:
-    raise WrongNumberOfArgumentsException('-o required.')
-
-  if options.list_outputs:
-    outputs = [posixpath.join(options.output_dir, x[1]) for x in files_to_copy]
-    return '\n'.join(outputs)
-
-  CopyFiles(files_to_copy, options.output_dir)
-  return
-
-
-def main(argv):
-  try:
-    result = DoMain(argv[1:])
-  except WrongNumberOfArgumentsException, e:
-    print >> sys.stderr, e
-    return 1
-  if result:
-    print result
-  return 0
-
-if __name__ == '__main__':
-  sys.exit(main(sys.argv))
diff --git a/src/cobalt/build/copy_test_data.gypi b/src/cobalt/build/copy_test_data.gypi
index e4e47ed..13ac050 100644
--- a/src/cobalt/build/copy_test_data.gypi
+++ b/src/cobalt/build/copy_test_data.gypi
@@ -50,14 +50,14 @@
 
 {
   'inputs': [
-    '<!@pymod_do_main(copy_data --inputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))',
   ],
   'outputs': [
-    '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))',
   ],
   'action': [
     'python',
-    '<(DEPTH)/cobalt/build/copy_data.py',
+    '<(DEPTH)/starboard/build/copy_data.py',
     '-o', '<(PRODUCT_DIR)/content/dir_source_root/<(output_dir)',
     '<@(input_files)',
   ],
diff --git a/src/cobalt/build/copy_web_data.gypi b/src/cobalt/build/copy_web_data.gypi
index 4585eb2..b4f5c98 100644
--- a/src/cobalt/build/copy_web_data.gypi
+++ b/src/cobalt/build/copy_web_data.gypi
@@ -50,14 +50,14 @@
 
 {
   'inputs': [
-    '<!@pymod_do_main(copy_data --inputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))',
   ],
   'outputs': [
-    '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/data/web/<(output_dir) --outputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/data/web/<(output_dir) --outputs <(input_files))',
   ],
   'action': [
     'python',
-    '<(DEPTH)/cobalt/build/copy_data.py',
+    '<(DEPTH)/starboard/build/copy_data.py',
     '-o', '<(PRODUCT_DIR)/content/data/web/<(output_dir)',
     '<@(input_files)',
   ],
diff --git a/src/cobalt/build/deploy.gypi b/src/cobalt/build/deploy.gypi
deleted file mode 100644
index d252e14..0000000
--- a/src/cobalt/build/deploy.gypi
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2014 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file is meant to be included into a target to provide a rule
-# to deploy a target on a target platform.
-#
-# To use this, create a gyp target with the following form:
-# 'targets': [
-#   {
-#     'target_name': 'target_deploy',
-#     'type': 'none',
-#     'dependencies': [
-#       'target',
-#     ],
-#     'variables': {
-#       'executable_name': 'target',
-#     },
-#     'includes': [
-#       '../build/deploy.gypi',
-#     ],
-#   },
-#
-
-{
-  'conditions': [
-    ['OS=="starboard" and sb_has_deploy_step==1', {
-      'dependencies': [
-        '<(DEPTH)/<(starboard_path)/build/platform_files.gyp:platform_files',
-      ],
-    }],
-  ],
-}
diff --git a/src/cobalt/build/gyp_cobalt b/src/cobalt/build/gyp_cobalt
index a683762..0e60bb9 100755
--- a/src/cobalt/build/gyp_cobalt
+++ b/src/cobalt/build/gyp_cobalt
@@ -191,6 +191,10 @@
         '--toplevel-dir={}'.format(source_tree_dir),
     ]
 
+    # Add the source tree root to the Python path so that build files can
+    # easily reference other build files in the source tree.
+    sys.path.append(source_tree_dir)
+
     # Pass through the debug options.
     for debug in self.options.debug:
       self.common_args.append('--debug=%s' % debug)
diff --git a/src/cobalt/csp/csp.gyp b/src/cobalt/csp/csp.gyp
index 846471d..a493cd7 100644
--- a/src/cobalt/csp/csp.gyp
+++ b/src/cobalt/csp/csp.gyp
@@ -73,7 +73,7 @@
       'variables': {
         'executable_name': 'csp_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
diff --git a/src/cobalt/css_parser/css_parser.gyp b/src/cobalt/css_parser/css_parser.gyp
index 088a212..185ee0b 100644
--- a/src/cobalt/css_parser/css_parser.gyp
+++ b/src/cobalt/css_parser/css_parser.gyp
@@ -144,7 +144,7 @@
       'variables': {
         'executable_name': 'css_parser_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
   ],
diff --git a/src/cobalt/cssom/cssom_test.gyp b/src/cobalt/cssom/cssom_test.gyp
index d61f561..a776fa4 100644
--- a/src/cobalt/cssom/cssom_test.gyp
+++ b/src/cobalt/cssom/cssom_test.gyp
@@ -70,7 +70,7 @@
       'variables': {
         'executable_name': 'cssom_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/debug/render_overlay.cc b/src/cobalt/debug/render_overlay.cc
index d769b99..85d03b0 100644
--- a/src/cobalt/debug/render_overlay.cc
+++ b/src/cobalt/debug/render_overlay.cc
@@ -40,24 +40,27 @@
 }
 
 void RenderOverlay::Process() {
-  // Calculate a modified layout time accounting for the offset between now and
-  // the time the input layout was received.
-  base::TimeDelta layout_time =
-      input_layout_.layout_time +
-      (base::TimeTicks::HighResNow() - *input_receipt_time_);
+  if (input_layout_.render_tree) {
+    // Calculate a modified layout time accounting for the offset between now
+    // and the time the input layout was received.
+    base::TimeDelta layout_time = input_layout_.layout_time;
+    DCHECK(input_receipt_time_);
+    base::TimeTicks now = base::TimeTicks::HighResNow();
+    layout_time += now - input_receipt_time_.value_or(now);
 
-  if (overlay_) {
-    render_tree::CompositionNode::Builder builder;
-    builder.AddChild(input_layout_.render_tree);
-    builder.AddChild(overlay_);
-    scoped_refptr<render_tree::Node> combined_tree =
-        new render_tree::CompositionNode(builder);
+    if (overlay_) {
+      render_tree::CompositionNode::Builder builder;
+      builder.AddChild(input_layout_.render_tree);
+      builder.AddChild(overlay_);
+      scoped_refptr<render_tree::Node> combined_tree =
+          new render_tree::CompositionNode(builder);
 
-    render_tree_produced_callback_.Run(
-        LayoutResults(combined_tree, input_layout_.animations, layout_time));
-  } else {
-    render_tree_produced_callback_.Run(LayoutResults(
-        input_layout_.render_tree, input_layout_.animations, layout_time));
+      render_tree_produced_callback_.Run(
+          LayoutResults(combined_tree, input_layout_.animations, layout_time));
+    } else {
+      render_tree_produced_callback_.Run(LayoutResults(
+          input_layout_.render_tree, input_layout_.animations, layout_time));
+    }
   }
 }
 
diff --git a/src/cobalt/deprecated/platform_delegate.cc b/src/cobalt/deprecated/platform_delegate.cc
index 98a6b62..6e7baaf 100644
--- a/src/cobalt/deprecated/platform_delegate.cc
+++ b/src/cobalt/deprecated/platform_delegate.cc
@@ -44,6 +44,8 @@
         *result = FilePath(plat->logging_output_path());
         return true;
       } else {
+        DLOG(ERROR) << "Unable to get or create paths::DIR_COBALT_DEBUG_OUT: "
+                    << plat->logging_output_path();
         return false;
       }
 
@@ -53,6 +55,8 @@
         *result = FilePath(plat->logging_output_path());
         return true;
       } else {
+        DLOG(ERROR) << "Unable to get or create paths::DIR_COBALT_TEST_OUT: "
+                    << plat->logging_output_path();
         return false;
       }
 
diff --git a/src/cobalt/dom/dom_test.gyp b/src/cobalt/dom/dom_test.gyp
index e255ee4..a399a4e 100644
--- a/src/cobalt/dom/dom_test.gyp
+++ b/src/cobalt/dom/dom_test.gyp
@@ -84,7 +84,7 @@
       'variables': {
         'executable_name': 'dom_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/dom/local_storage_database_test.cc b/src/cobalt/dom/local_storage_database_test.cc
index af56dd2..55963ec 100644
--- a/src/cobalt/dom/local_storage_database_test.cc
+++ b/src/cobalt/dom/local_storage_database_test.cc
@@ -18,8 +18,8 @@
 
 #include <vector>
 
-#include "base/message_loop.h"
 #include "base/file_path.h"
+#include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/stringprintf.h"
 #include "base/time.h"
@@ -41,7 +41,7 @@
   CallbackWaiter() : was_called_event_(true, false) {}
   virtual ~CallbackWaiter() {}
   bool TimedWait() {
-    return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500));
+    return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5));
   }
 
  protected:
diff --git a/src/cobalt/dom/node.cc b/src/cobalt/dom/node.cc
index c36ffe7..cf81ef0 100644
--- a/src/cobalt/dom/node.cc
+++ b/src/cobalt/dom/node.cc
@@ -601,6 +601,7 @@
 
   OnMutation();
   InvalidateLayoutBoxesFromNodeAndAncestors();
+  node->InvalidateLayoutBoxesFromNodeAndDescendants();
   node->UpdateGenerationForNodeAndAncestors();
 
   bool was_inserted_to_document = node->inserted_into_document_;
diff --git a/src/cobalt/dom_parser/dom_parser.gyp b/src/cobalt/dom_parser/dom_parser.gyp
index ca12a0f..76ba70a 100644
--- a/src/cobalt/dom_parser/dom_parser.gyp
+++ b/src/cobalt/dom_parser/dom_parser.gyp
@@ -67,7 +67,7 @@
       'variables': {
         'executable_name': 'dom_parser_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/h5vcc/H5vccAccountManager.idl b/src/cobalt/h5vcc/H5vccAccountManager.idl
new file mode 100644
index 0000000..3192c74
--- /dev/null
+++ b/src/cobalt/h5vcc/H5vccAccountManager.idl
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+[
+  Conditional=COBALT_ENABLE_ACCOUNT_MANAGER,
+  Constructor
+]
+interface H5vccAccountManager {
+  void getAuthToken(AccessTokenCallback callback);
+  void requestPairing(AccessTokenCallback callback);
+  void requestUnpairing(AccessTokenCallback callback);
+};
+
+callback AccessTokenCallback = boolean(DOMString token,
+                                       unsigned long long expiration);
diff --git a/src/cobalt/h5vcc/h5vcc.gyp b/src/cobalt/h5vcc/h5vcc.gyp
index a91d751..835c4f9 100644
--- a/src/cobalt/h5vcc/h5vcc.gyp
+++ b/src/cobalt/h5vcc/h5vcc.gyp
@@ -57,6 +57,19 @@
         # For cobalt_build_id.h
         '<(SHARED_INTERMEDIATE_DIR)',
       ],
+      'conditions': [
+        ['enable_account_manager == 1', {
+          'sources': [
+            'h5vcc_account_manager.cc',
+            'h5vcc_account_manager.h',
+          ],
+          'direct_dependent_settings': {
+            'defines': [
+              'COBALT_ENABLE_ACCOUNT_MANAGER',
+            ],
+          },
+        }],
+      ],
     },
 
     {
diff --git a/src/cobalt/h5vcc/h5vcc_account_manager.cc b/src/cobalt/h5vcc/h5vcc_account_manager.cc
new file mode 100644
index 0000000..69dd9db
--- /dev/null
+++ b/src/cobalt/h5vcc/h5vcc_account_manager.cc
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/h5vcc/h5vcc_account_manager.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "starboard/user.h"
+
+namespace cobalt {
+namespace h5vcc {
+
+H5vccAccountManager::H5vccAccountManager()
+    : thread_("AccountManager"), owning_message_loop_(MessageLoop::current()) {
+  thread_.Start();
+}
+
+void H5vccAccountManager::GetAuthToken(
+    const AccessTokenCallbackHolder& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DLOG(INFO) << "Get authorization token.";
+  scoped_ptr<AccessTokenCallbackReference> token_callback(
+      new AccessTokenCallbackHolder::Reference(this, callback));
+  thread_.message_loop()->PostTask(
+      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
+                            this, kGetToken, base::Passed(&token_callback)));
+}
+
+void H5vccAccountManager::RequestPairing(
+    const AccessTokenCallbackHolder& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DLOG(INFO) << "Request application linking.";
+  scoped_ptr<AccessTokenCallbackReference> token_callback(
+      new AccessTokenCallbackHolder::Reference(this, callback));
+  thread_.message_loop()->PostTask(
+      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
+                            this, kPairing, base::Passed(&token_callback)));
+}
+
+void H5vccAccountManager::RequestUnpairing(
+    const AccessTokenCallbackHolder& callback) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DLOG(INFO) << "Request application unlinking.";
+  scoped_ptr<AccessTokenCallbackReference> token_callback(
+      new AccessTokenCallbackHolder::Reference(this, callback));
+  thread_.message_loop()->PostTask(
+      FROM_HERE, base::Bind(&H5vccAccountManager::RequestOperationInternal,
+                            this, kUnpairing, base::Passed(&token_callback)));
+}
+
+H5vccAccountManager::~H5vccAccountManager() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void H5vccAccountManager::RequestOperationInternal(
+    OperationType operation,
+    scoped_ptr<AccessTokenCallbackReference> token_callback) {
+  DCHECK_EQ(thread_.message_loop(), MessageLoop::current());
+
+  SbUser current_user = SbUserGetCurrent();
+  DCHECK(SbUserIsValid(current_user));
+
+  static size_t kBufferSize = SbUserMaxAuthenticationTokenSizeInBytes();
+  scoped_array<char> token_buffer(new char[kBufferSize]);
+  SbUserApplicationTokenResults token_results;
+  token_results.token_buffer_size = kBufferSize;
+  token_results.token_buffer = token_buffer.get();
+
+  bool got_valid_token = false;
+  switch (operation) {
+    case kPairing:
+      got_valid_token =
+          SbUserRequestApplicationLinking(current_user, &token_results);
+      DLOG_IF(INFO, !got_valid_token) << "Application linking request failed.";
+      break;
+    case kUnpairing:
+      if (SbUserRequestApplicationUnlinking(current_user)) {
+        got_valid_token = false;
+        break;
+      }
+      // The user canceled the flow, or there was some error. Fall into the next
+      // case to get an access token if available and return that.
+      DLOG(INFO) << "Application unlinking request failed. Try to get token.";
+    case kGetToken:
+      got_valid_token =
+          SbUserRequestAuthenticationToken(current_user, &token_results);
+      DLOG_IF(INFO, !got_valid_token) << "Authentication token request failed.";
+      break;
+  }
+
+  uint64_t expiration_in_seconds = 0;
+  if (got_valid_token) {
+    SbTime expires_in = token_results.expiry - SbTimeGetNow();
+    // If this token's expiry is in the past, then we didn't get a valid token.
+    if (expires_in < 0) {
+      DLOG(WARNING) << "Authentication token expires in the past.";
+      got_valid_token = false;
+    } else {
+      expiration_in_seconds = expires_in / kSbTimeSecond;
+    }
+  }
+  // If we did not get a valid token to return to the caller, set the token
+  // buffer to an empty string.
+  if (!got_valid_token) {
+    token_buffer[0] = '\0';
+  }
+
+  owning_message_loop_->PostTask(
+      FROM_HERE,
+      base::Bind(&H5vccAccountManager::SendResult, this,
+                 base::Passed(&token_callback), std::string(token_buffer.get()),
+                 expiration_in_seconds));
+}
+
+void H5vccAccountManager::SendResult(
+    scoped_ptr<AccessTokenCallbackReference> token_callback,
+    const std::string& token, uint64_t expiration_in_seconds) {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  token_callback->value().Run(token, expiration_in_seconds);
+}
+
+}  // namespace h5vcc
+}  // namespace cobalt
diff --git a/src/cobalt/h5vcc/h5vcc_account_manager.h b/src/cobalt/h5vcc/h5vcc_account_manager.h
new file mode 100644
index 0000000..3c5c6a4
--- /dev/null
+++ b/src/cobalt/h5vcc/h5vcc_account_manager.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_
+#define COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_
+
+#include <queue>
+#include <string>
+
+#include "base/message_loop.h"
+#include "base/threading/thread.h"
+#include "base/threading/thread_checker.h"
+#include "cobalt/script/callback_function.h"
+#include "cobalt/script/script_object.h"
+#include "cobalt/script/wrappable.h"
+
+namespace cobalt {
+namespace h5vcc {
+
+// Implementation of the H5vccAccountManager interface. Requests will be handled
+// one-at-time on another thread in FIFO order. When a request is complete, the
+// AccessTokenCallback will be fired on the thread that the H5vccAccountManager
+// was created on.
+class H5vccAccountManager : public script::Wrappable {
+ public:
+  typedef script::CallbackFunction<bool(const std::string&, uint64_t)>
+      AccessTokenCallback;
+  typedef script::ScriptObject<AccessTokenCallback> AccessTokenCallbackHolder;
+
+  H5vccAccountManager();
+  // H5vccAccountManager interface.
+  void GetAuthToken(const AccessTokenCallbackHolder& callback);
+  void RequestPairing(const AccessTokenCallbackHolder& callback);
+  void RequestUnpairing(const AccessTokenCallbackHolder& callback);
+
+  DEFINE_WRAPPABLE_TYPE(H5vccAccountManager);
+
+ private:
+  typedef script::ScriptObject<AccessTokenCallback>::Reference
+      AccessTokenCallbackReference;
+  enum OperationType {
+    kPairing,
+    kUnpairing,
+    kGetToken,
+  };
+
+  ~H5vccAccountManager();
+
+  void RequestOperationInternal(
+      OperationType operation,
+      scoped_ptr<AccessTokenCallbackReference> token_callback);
+  void SendResult(scoped_ptr<AccessTokenCallbackReference> token_callback,
+                        const std::string& token,
+                        uint64_t expiration_in_seconds);
+
+  // Thread checker for the thread that creates this instance.
+  base::ThreadChecker thread_checker_;
+
+  // Each incoming request will have a corresponding task posted to this
+  // thread's message loop and will be handled in a FIFO manner.
+  base::Thread thread_;
+
+  // The message loop that the H5vccAccountManager was created on. The public
+  // interface must be called from this message loop, and callbacks will be
+  // fired on this loop as well.
+  MessageLoop* owning_message_loop_;
+
+  friend class scoped_refptr<H5vccAccountManager>;
+  DISALLOW_COPY_AND_ASSIGN(H5vccAccountManager);
+};
+
+}  // namespace h5vcc
+}  // namespace cobalt
+
+#endif  // COBALT_H5VCC_H5VCC_ACCOUNT_MANAGER_H_
diff --git a/src/cobalt/layout/block_container_box.cc b/src/cobalt/layout/block_container_box.cc
index 57e34d7..79ad027 100644
--- a/src/cobalt/layout/block_container_box.cc
+++ b/src/cobalt/layout/block_container_box.cc
@@ -246,6 +246,7 @@
     WrapOpportunityPolicy /*wrap_opportunity_policy*/,
     bool /*is_line_existence_justified*/, LayoutUnit /*available_width*/,
     bool /*should_collapse_trailing_white_space*/) {
+  DCHECK(!IsAbsolutelyPositioned());
   DCHECK_EQ(kInlineLevel, GetLevel());
   return kWrapResultNoWrap;
 }
diff --git a/src/cobalt/layout/block_formatting_block_container_box.cc b/src/cobalt/layout/block_formatting_block_container_box.cc
index 336aef4..b4023d8 100644
--- a/src/cobalt/layout/block_formatting_block_container_box.cc
+++ b/src/cobalt/layout/block_formatting_block_container_box.cc
@@ -158,6 +158,7 @@
     bool is_line_existence_justified, LayoutUnit /*available_width*/,
     bool /*should_collapse_trailing_white_space*/) {
   // NOTE: This logic must stay in sync with ReplacedBox::TryWrapAt().
+  DCHECK(!IsAbsolutelyPositioned());
 
   // Wrapping is not allowed until the line's existence is justified, meaning
   // that wrapping cannot occur before the box. Given that this box cannot be
diff --git a/src/cobalt/layout/box_generator.cc b/src/cobalt/layout/box_generator.cc
index 09024973..a2affb9 100644
--- a/src/cobalt/layout/box_generator.cc
+++ b/src/cobalt/layout/box_generator.cc
@@ -315,13 +315,19 @@
     return;
   }
 
+  scoped_refptr<cssom::CSSComputedStyleDeclaration>
+      css_computed_style_declaration = new cssom::CSSComputedStyleDeclaration();
+  css_computed_style_declaration->set_data(
+      GetComputedStyleOfAnonymousBox(br_element->computed_style()));
+
+  css_computed_style_declaration->set_animations(br_element->animations());
+
   DCHECK(*paragraph_);
   int32 text_position = (*paragraph_)->GetTextEndPosition();
 
-  scoped_refptr<TextBox> br_text_box =
-      new TextBox(br_element->css_computed_style_declaration(), *paragraph_,
-                  text_position, text_position, true,
-                  context_->used_style_provider, context_->layout_stat_tracker);
+  scoped_refptr<TextBox> br_text_box = new TextBox(
+      css_computed_style_declaration, *paragraph_, text_position, text_position,
+      true, context_->used_style_provider, context_->layout_stat_tracker);
 
   // Add a line feed code point to the paragraph to signify the new line for
   // the line breaking and bidirectional algorithms.
diff --git a/src/cobalt/layout/container_box.cc b/src/cobalt/layout/container_box.cc
index 2fd8818..24f72b1 100644
--- a/src/cobalt/layout/container_box.cc
+++ b/src/cobalt/layout/container_box.cc
@@ -89,11 +89,7 @@
   // https://www.w3.org/TR/css-transforms-1/#transformable-element
   DCHECK(!split_sibling->IsTransformable());
   if (split_sibling->IsPositioned()) {
-    // Absolutely positioned boxes are not splittable.
-    DCHECK(!split_sibling->IsAbsolutelyPositioned());
-    // This container is the containing block because the split sibling cannot
-    // be an absolutely positioned box.
-    are_cross_references_valid_ = false;
+    split_sibling->GetContainingBlock()->are_cross_references_valid_ = false;
     split_sibling->GetStackingContext()->are_cross_references_valid_ = false;
   }
 
diff --git a/src/cobalt/layout/inline_container_box.cc b/src/cobalt/layout/inline_container_box.cc
index 6d8ae8e..062bc6e 100644
--- a/src/cobalt/layout/inline_container_box.cc
+++ b/src/cobalt/layout/inline_container_box.cc
@@ -181,6 +181,7 @@
     WrapAtPolicy wrap_at_policy, WrapOpportunityPolicy wrap_opportunity_policy,
     bool is_line_existence_justified, LayoutUnit available_width,
     bool should_collapse_trailing_white_space) {
+  DCHECK(!IsAbsolutelyPositioned());
   DCHECK(is_line_existence_justified || justifies_line_existence_);
 
   switch (wrap_at_policy) {
@@ -469,7 +470,13 @@
   // set to the number of child boxes.
   size_t overflow_index = 0;
   while (overflow_index < child_boxes().size()) {
-    LayoutUnit child_width = child_boxes()[overflow_index]->GetMarginBoxWidth();
+    Box* child_box = child_boxes()[overflow_index];
+    // Absolutely positioned boxes are not included in width calculations.
+    if (child_box->IsAbsolutelyPositioned()) {
+      continue;
+    }
+
+    LayoutUnit child_width = child_box->GetMarginBoxWidth();
     if (child_width > available_width) {
       break;
     }
@@ -563,6 +570,10 @@
     bool is_line_existence_justified, LayoutUnit available_width,
     bool should_collapse_trailing_white_space) {
   Box* child_box = child_boxes()[wrap_index];
+  // Absolutely positioned boxes are not wrappable.
+  if (child_box->IsAbsolutelyPositioned()) {
+    return kWrapResultNoWrap;
+  }
 
   // Check for whether the line is justified before this child. If it is not,
   // then verify that the line is justified within this child. This function
diff --git a/src/cobalt/layout/layout.gyp b/src/cobalt/layout/layout.gyp
index 5aa740c..cde6dba 100644
--- a/src/cobalt/layout/layout.gyp
+++ b/src/cobalt/layout/layout.gyp
@@ -131,7 +131,7 @@
       'variables': {
         'executable_name': 'layout_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/layout/line_box.cc b/src/cobalt/layout/line_box.cc
index be56c64..9012f31 100644
--- a/src/cobalt/layout/line_box.cc
+++ b/src/cobalt/layout/line_box.cc
@@ -347,6 +347,14 @@
 bool LineBox::TryWrapOverflowingBoxAndMaybeAddSplitChild(
     WrapAtPolicy wrap_at_policy, WrapOpportunityPolicy wrap_opportunity_policy,
     Box* child_box) {
+  // If none of the children justify the line's existence, then wrapping is
+  // unavailable. The wrap can't happen before the first child justifying the
+  // line.
+  if (!first_box_justifying_line_existence_index_ &&
+      !child_box->JustifiesLineExistence()) {
+    return false;
+  }
+
   // Attempt to wrap the child based upon the passed in wrap policy.
   WrapResult wrap_result = child_box->TryWrapAt(
       wrap_at_policy, wrap_opportunity_policy, LineExists(),
diff --git a/src/cobalt/layout/replaced_box.cc b/src/cobalt/layout/replaced_box.cc
index a24ba76..62b771f 100644
--- a/src/cobalt/layout/replaced_box.cc
+++ b/src/cobalt/layout/replaced_box.cc
@@ -94,6 +94,7 @@
     bool /*should_collapse_trailing_white_space*/) {
   // NOTE: This logic must stay in sync with
   // InlineLevelBlockContainerBox::TryWrapAt().
+  DCHECK(!IsAbsolutelyPositioned());
 
   // Wrapping is not allowed until the line's existence is justified, meaning
   // that wrapping cannot occur before the box. Given that this box cannot be
diff --git a/src/cobalt/layout/text_box.cc b/src/cobalt/layout/text_box.cc
index f5413ef..84e5823 100644
--- a/src/cobalt/layout/text_box.cc
+++ b/src/cobalt/layout/text_box.cc
@@ -165,6 +165,8 @@
                               bool is_line_existence_justified,
                               LayoutUnit available_width,
                               bool should_collapse_trailing_white_space) {
+  DCHECK(!IsAbsolutelyPositioned());
+
   bool style_allows_break_word =
       computed_style()->overflow_wrap() == cssom::KeywordValue::GetBreakWord();
 
@@ -265,7 +267,7 @@
 
 bool TextBox::IsCollapsed() const {
   return !HasLeadingWhiteSpace() && !HasTrailingWhiteSpace() &&
-         !HasNonCollapsibleText() && !has_trailing_line_break_;
+         !HasNonCollapsibleText();
 }
 
 bool TextBox::HasLeadingWhiteSpace() const {
diff --git a/src/cobalt/layout_tests/layout_tests.gyp b/src/cobalt/layout_tests/layout_tests.gyp
index 5cf6941..454e3f2 100644
--- a/src/cobalt/layout_tests/layout_tests.gyp
+++ b/src/cobalt/layout_tests/layout_tests.gyp
@@ -87,7 +87,7 @@
       'variables': {
         'executable_name': 'layout_tests',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
@@ -117,7 +117,7 @@
       'variables': {
         'executable_name': 'layout_benchmarks',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
     {
       'target_name': 'web_platform_tests',
@@ -148,7 +148,7 @@
       'variables': {
         'executable_name': 'web_platform_tests',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
   ],
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png
index 234d180..358cba3 100644
--- a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png
+++ b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html
index 4582fbd..fe3ccf4 100644
--- a/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html
+++ b/src/cobalt/layout_tests/testdata/css-text-3/4-1-1-space-preceding-br-element-should-not-be-collapsed.html
@@ -1,9 +1,6 @@
 <!DOCTYPE html>
 <!--
- | The spec is ambiguous on how to handle whitespace preceding a <br>
- | element on a line and browsers are not consistent in their
- | handling of it. As a result, we're preventing whitespace collapsing
- | preceding <br> elements to match Chrome's functionality.
+ | Whitespace preceding a <br> element should be collapsed.
  |   https://www.w3.org/TR/css3-text/#white-space-phase-1
  -->
 <html>
@@ -15,12 +12,20 @@
       font-size: 50px;
       font-weight: bold;
     }
+    .wrap-block {
+      width: 180px;
+    }
+    .blue-background {
+      background-color: #4285f4;
+    }
     .collapsed {
       background-color: #f50057;
     }
   </style>
 </head>
 <body>
+  <div class="wrap-block blue-background">Hi there <br>world!</div>
+  <div><span class="blue-background">Hello, <br></span>world!</div>
   <div>Hello,<span class="collapsed"> <br></span>world!</div>
   <div>Hello,<span class="collapsed"> </span><br>world!</div>
 </body>
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png
new file mode 100644
index 0000000..bb1b326
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping-expected.png
Binary files differ
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html
new file mode 100644
index 0000000..17b1db3
--- /dev/null
+++ b/src/cobalt/layout_tests/testdata/css-text-3/5-absolute-boxes-in-span-should-not-impact-line-wrapping.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<!--
+ | Absolutely positioned boxes should not be considered during line
+ | wrapping.
+ -->
+<html>
+<head>
+  <style>
+    body {
+      margin: 0px;
+      font-family: Roboto;
+      font-size: 20px;
+    }
+    .containing-block {
+      background-color: #03a9f4;
+      width: 100px;
+    }
+    .absolute-block {
+      position: absolute;
+      margin: 40px;
+    }
+  </style>
+</head>
+<body>
+  <div class="containing-block">
+    <div><span>abcdefghijkl<span class="absolute-block"> mnop</span>qrst</span></div>
+  </div>
+</body>
+</html>
diff --git a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
index fbb14be..a001297 100644
--- a/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
+++ b/src/cobalt/layout_tests/testdata/css-text-3/layout_tests.txt
@@ -29,6 +29,7 @@
 4-1-1-space-preceding-br-element-should-not-be-collapsed
 4-1-3-spaces-at-beginning-and-end-of-line-should-be-collapsed
 4-1-empty-inline-block-should-be-treated-as-non-empty-text
+5-absolute-boxes-in-span-should-not-impact-line-wrapping
 5-collapsible-leading-white-space-should-not-prevent-soft-wrap-opportunity
 5-collapsible-trailing-white-space-should-not-prevent-soft-wrap-opportunity
 5-collapsible-trailing-white-space-that-overflows-line-prior-to-collapse-should-not-cause-wrap
diff --git a/src/cobalt/loader/image/jpeg_image_decoder.cc b/src/cobalt/loader/image/jpeg_image_decoder.cc
index da8c73e..a249c7e 100644
--- a/src/cobalt/loader/image/jpeg_image_decoder.cc
+++ b/src/cobalt/loader/image/jpeg_image_decoder.cc
@@ -331,6 +331,7 @@
       case render_tree::kPixelFormatY8:
       case render_tree::kPixelFormatU8:
       case render_tree::kPixelFormatV8:
+      case render_tree::kPixelFormatUV8:
       case render_tree::kPixelFormatInvalid: {
         NOTREACHED();
       } break;
diff --git a/src/cobalt/loader/image/png_image_decoder.cc b/src/cobalt/loader/image/png_image_decoder.cc
index 5e56c69..e048d41 100644
--- a/src/cobalt/loader/image/png_image_decoder.cc
+++ b/src/cobalt/loader/image/png_image_decoder.cc
@@ -309,6 +309,7 @@
     case render_tree::kPixelFormatY8:
     case render_tree::kPixelFormatU8:
     case render_tree::kPixelFormatV8:
+    case render_tree::kPixelFormatUV8:
     case render_tree::kPixelFormatInvalid: {
       NOTREACHED();
     } break;
diff --git a/src/cobalt/loader/image/sandbox/sandbox.gyp b/src/cobalt/loader/image/sandbox/sandbox.gyp
index 084bd31..88e4597 100644
--- a/src/cobalt/loader/image/sandbox/sandbox.gyp
+++ b/src/cobalt/loader/image/sandbox/sandbox.gyp
@@ -45,7 +45,7 @@
       'variables': {
         'executable_name': 'image_decoder_sandbox',
       },
-      'includes': [ '../../../build/deploy.gypi' ],
+      'includes': [ '../../../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/loader/loader.gyp b/src/cobalt/loader/loader.gyp
index 230a91e..0b6698f 100644
--- a/src/cobalt/loader/loader.gyp
+++ b/src/cobalt/loader/loader.gyp
@@ -116,7 +116,7 @@
       'variables': {
         'executable_name': 'loader_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
diff --git a/src/cobalt/math/math.gyp b/src/cobalt/math/math.gyp
index c619a84..2752104 100644
--- a/src/cobalt/math/math.gyp
+++ b/src/cobalt/math/math.gyp
@@ -104,7 +104,7 @@
       'variables': {
         'executable_name': 'math_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/media/fetcher_buffered_data_source.cc b/src/cobalt/media/fetcher_buffered_data_source.cc
index 33af77b..3d96ea7 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.cc
+++ b/src/cobalt/media/fetcher_buffered_data_source.cc
@@ -28,6 +28,16 @@
 namespace cobalt {
 namespace media {
 
+namespace {
+
+const uint32 kBackwardBytes = 256 * 1024;
+const uint32 kInitialForwardBytes = 3 * 256 * 1024;
+const uint32 kInitialBufferCapacity = kBackwardBytes + kInitialForwardBytes;
+
+}  // namespace
+
+using base::CircularBufferShell;
+
 FetcherBufferedDataSource::FetcherBufferedDataSource(
     const scoped_refptr<base::MessageLoopProxy>& message_loop, const GURL& url,
     const csp::SecurityCallback& security_callback,
@@ -35,7 +45,7 @@
     : message_loop_(message_loop),
       url_(url),
       network_module_(network_module),
-      buffer_(kBufferCapacity, base::CircularBufferShell::kReserve),
+      buffer_(kInitialBufferCapacity, CircularBufferShell::kReserve),
       buffer_offset_(0),
       error_occured_(false),
       last_request_offset_(0),
@@ -57,6 +67,11 @@
   DCHECK_GE(position, 0);
   DCHECK_GE(size, 0);
 
+  if (position < 0 || size < 0) {
+    read_cb.Run(kInvalidSize);
+    return;
+  }
+
   base::AutoLock auto_lock(lock_);
   Read_Locked(static_cast<uint64>(position), static_cast<uint64>(size), data,
               read_cb);
@@ -206,11 +221,13 @@
   }
 
   // If we are overflow, remove some data from the front of the buffer_.
-  if (buffer_.GetLength() + size > kBufferCapacity) {
+  if (buffer_.GetLength() + size > buffer_.GetMaxCapacity()) {
     size_t bytes_skipped;
-    buffer_.Skip(buffer_.GetLength() + size - kBufferCapacity, &bytes_skipped);
-    // "+ 0" converts kBufferCapacity into a r-value to avoid link error.
-    DCHECK_EQ(buffer_.GetLength() + size, kBufferCapacity + 0);
+    buffer_.Skip(buffer_.GetLength() + size - buffer_.GetMaxCapacity(),
+                 &bytes_skipped);
+    // "+ 0" converts buffer_.GetMaxCapacity() into a r-value to avoid link
+    // error.
+    DCHECK_EQ(buffer_.GetLength() + size, buffer_.GetMaxCapacity() + 0);
     buffer_offset_ += bytes_skipped;
   }
 
@@ -360,14 +377,24 @@
   // Now we have to issue a new fetch and we no longer care about the range
   // of the current fetch in progress if there is any.  Ideally the request
   // range starts at |last_read_position_ - kBackwardBytes| with length of
-  // kBufferCapacity.
+  // buffer_.GetMaxCapacity().
   if (last_read_position_ > kBackwardBytes) {
     last_request_offset_ = last_read_position_ - kBackwardBytes;
   } else {
     last_request_offset_ = 0;
   }
 
-  last_request_size_ = kBufferCapacity;
+  size_t required_size =
+      last_read_position_ - last_request_offset_ + pending_read_size_;
+  if (required_size > buffer_.GetMaxCapacity()) {
+    // The capacity of the current buffer is not large enough to hold the
+    // pending read.
+    size_t new_capacity =
+        std::max<size_t>(buffer_.GetMaxCapacity() * 2, required_size);
+    buffer_.IncreaseMaxCapacityTo(new_capacity);
+  }
+
+  last_request_size_ = buffer_.GetMaxCapacity();
 
   if (last_request_offset_ >= buffer_offset_ &&
       last_request_offset_ <= buffer_offset_ + buffer_.GetLength()) {
diff --git a/src/cobalt/media/fetcher_buffered_data_source.h b/src/cobalt/media/fetcher_buffered_data_source.h
index 1c2dd04..530f403 100644
--- a/src/cobalt/media/fetcher_buffered_data_source.h
+++ b/src/cobalt/media/fetcher_buffered_data_source.h
@@ -55,9 +55,6 @@
 class FetcherBufferedDataSource : public ::media::BufferedDataSource,
                                   private net::URLFetcherDelegate {
  public:
-  static const uint32 kBackwardBytes = 256 * 1024;
-  static const uint32 kForwardBytes = 3 * 256 * 1024;
-  static const uint32 kBufferCapacity = kBackwardBytes + kForwardBytes;
   static const int64 kInvalidSize = -1;
 
   // Because the Fetchers have to be created and destroyed on the same thread,
diff --git a/src/cobalt/media/media_module.h b/src/cobalt/media/media_module.h
index addced3..933b214 100644
--- a/src/cobalt/media/media_module.h
+++ b/src/cobalt/media/media_module.h
@@ -31,6 +31,7 @@
 #include "cobalt/render_tree/resource_provider.h"
 #include "media/base/shell_media_platform.h"
 #include "media/base/shell_video_frame_provider.h"
+#include "media/filters/shell_video_decoder_impl.h"
 #include "media/player/web_media_player_delegate.h"
 
 namespace cobalt {
@@ -64,6 +65,12 @@
     return false;
   }
 
+#if !defined(COBALT_BUILD_TYPE_GOLD)
+  virtual ::media::ShellRawVideoDecoderFactory* GetRawVideoDecoderFactory() {
+    return NULL;
+  }
+#endif  // !defined(COBALT_RELEASE)
+
   // TODO: Move the following methods into class like MediaModuleBase
   // to ensure that MediaModule is an interface.
   // WebMediaPlayerDelegate methods
diff --git a/src/cobalt/media/sandbox/fuzzer_app.cc b/src/cobalt/media/sandbox/fuzzer_app.cc
new file mode 100644
index 0000000..4495e34
--- /dev/null
+++ b/src/cobalt/media/sandbox/fuzzer_app.cc
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/media/sandbox/fuzzer_app.h"
+
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "starboard/directory.h"
+#include "starboard/string.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+FuzzerApp::FuzzerApp() : number_of_iterations_(-1) {}
+
+bool FuzzerApp::Init(int argc, char* argv[], double min_ratio,
+                     double max_ratio) {
+  file_entries_.clear();
+
+  int initial_seed;
+  if (ParseInitialSeedAndNumberOfIterations(argc, argv, &initial_seed)) {
+    CollectFiles(argv[argc - 1], min_ratio, max_ratio, initial_seed);
+  }
+  return !file_entries_.empty() && number_of_iterations_ > 0;
+}
+
+void FuzzerApp::RunFuzzingLoop() {
+  DCHECK_GT(number_of_iterations_, 0);
+
+  for (int i = 0; i < number_of_iterations_; ++i) {
+    for (size_t file_index = 0; file_index < file_entries_.size();
+         ++file_index) {
+      LOG(INFO) << "Fuzzing \"" << file_entries_[file_index].file_name << "\" "
+                << "with seed " << file_entries_[file_index].fuzzer.seed();
+
+      Fuzz(file_entries_[file_index].file_name,
+           file_entries_[file_index].fuzzer.GetFuzzedContent());
+      file_entries_[file_index].fuzzer.AdvanceSeed();
+    }
+  }
+}
+
+bool FuzzerApp::ParseInitialSeedAndNumberOfIterations(int argc, char* argv[],
+                                                      int* initial_seed) {
+  DCHECK(initial_seed);
+
+  *initial_seed = ZzufFuzzer::kSeedForOriginalContent;
+
+  if (argc != 3 && argc != 4) {
+    LOG(ERROR) << "Usage: " << argv[0]
+               << " [initial seed (non-negative integer)]"
+               << " <number of iterations>"
+               << " <file name|directory name contains files to be fuzzed>";
+    LOG(ERROR) << "For example: " << argv[0] << " 200000 /data/video-files";
+    LOG(ERROR) << "             " << argv[0] << " 115 200000 /data/video-files";
+    return false;
+  }
+
+  if (argc == 3) {
+    *initial_seed = ZzufFuzzer::kSeedForOriginalContent;
+    number_of_iterations_ = SbStringParseSignedInteger(argv[1], NULL, 10);
+
+    if (number_of_iterations_ <= 0) {
+      LOG(ERROR) << "Invalid 'number of iterations' " << argv[1];
+      return false;
+    }
+  } else {
+    DCHECK_EQ(argc, 4);
+    *initial_seed = SbStringParseSignedInteger(argv[1], NULL, 10);
+
+    if (*initial_seed < 0) {
+      LOG(ERROR) << "Invalid 'initial seed' " << argv[1];
+      return false;
+    }
+
+    number_of_iterations_ = SbStringParseSignedInteger(argv[2], NULL, 10);
+
+    if (number_of_iterations_ <= 0) {
+      LOG(ERROR) << "Invalid 'number of iterations' " << argv[2];
+      return false;
+    }
+  }
+
+  return true;
+}
+
+void FuzzerApp::CollectFiles(const std::string& path_name, double min_ratio,
+                             double max_ratio, int initial_seed) {
+  file_entries_.clear();
+
+  SbDirectory directory = SbDirectoryOpen(path_name.c_str(), NULL);
+  if (!SbDirectoryIsValid(directory)) {
+    // Assuming it is a file.
+    AddFile(path_name, min_ratio, max_ratio, initial_seed);
+    return;
+  }
+
+  SbDirectoryEntry entry;
+  while (SbDirectoryGetNext(directory, &entry)) {
+    std::string file_name = path_name + SB_FILE_SEP_STRING + entry.name;
+    AddFile(file_name, min_ratio, max_ratio, initial_seed);
+  }
+
+  SbDirectoryClose(directory);
+}
+
+void FuzzerApp::AddFile(const std::string& file_name, double min_ratio,
+                        double max_ratio, int initial_seed) {
+  LOG(INFO) << "Loading " << file_name;
+
+  std::string content;
+  if (!file_util::ReadFileToString(FilePath(file_name), &content)) {
+    LOG(ERROR) << "Failed to load file " << file_name;
+    return;
+  }
+  if (content.empty()) {
+    LOG(ERROR) << file_name << " is empty";
+    return;
+  }
+  std::vector<uint8> uint8_content(content.begin(), content.end());
+  std::vector<uint8> parsed_content =
+      ParseFileContent(file_name, uint8_content);
+  if (parsed_content.empty()) {
+    return;
+  }
+  file_entries_.push_back(FileEntry(file_name, uint8_content, parsed_content,
+                                    min_ratio, max_ratio, initial_seed));
+}
+
+FuzzerApp::FileEntry::FileEntry(const std::string& file_name,
+                                const std::vector<uint8>& file_content,
+                                const std::vector<uint8>& fuzz_content,
+                                double min_ratio, double max_ratio,
+                                int initial_seed)
+    : file_name(file_name),
+      file_content(file_content),
+      fuzzer(fuzz_content, min_ratio, max_ratio, initial_seed) {}
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
diff --git a/src/cobalt/media/sandbox/fuzzer_app.h b/src/cobalt/media/sandbox/fuzzer_app.h
new file mode 100644
index 0000000..03292a3
--- /dev/null
+++ b/src/cobalt/media/sandbox/fuzzer_app.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MEDIA_SANDBOX_FUZZER_APP_H_
+#define COBALT_MEDIA_SANDBOX_FUZZER_APP_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "cobalt/media/sandbox/zzuf_fuzzer.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+// This class provides common functionalities required by fuzzer applications
+// including command line parsing, file data collecting, and the fuzzing loop.
+class FuzzerApp {
+ public:
+  FuzzerApp();
+
+  bool Init(int argc, char* argv[], double min_ratio = 0.01f,
+            double max_ratio = 0.05f);
+  void RunFuzzingLoop();
+
+  // This function parse |file_content| and returns the content used to fuzz.
+  // The return value may be different than |file_content|.  It will be used to
+  // generate the |fuzzing_content| parameter passed to Fuzz().
+  // The derived class may also take this opportunity to initialize any other
+  // data required by the fuzzing process and associate with |file_name|.
+  // If the return value is empty, the file will be excluded during the fuzzing
+  // process.
+  virtual std::vector<uint8> ParseFileContent(
+      const std::string& file_name, const std::vector<uint8>& file_content) = 0;
+  virtual void Fuzz(const std::string& file_name,
+                    const std::vector<uint8>& fuzzing_content) = 0;
+
+ protected:
+  ~FuzzerApp() {}
+
+ private:
+  struct FileEntry {
+    std::string file_name;
+    std::vector<uint8> file_content;
+    ZzufFuzzer fuzzer;
+
+    FileEntry(const std::string& file_name,
+              const std::vector<uint8>& file_content,
+              const std::vector<uint8>& fuzz_content, double min_ratio,
+              double max_ratio, int initial_seed);
+  };
+
+  bool ParseInitialSeedAndNumberOfIterations(int argc, char* argv[],
+                                             int* initial_seed);
+  void CollectFiles(const std::string& path_name, double min_ratio,
+                    double max_ratio, int initial_seed);
+  void AddFile(const std::string& file_name, double min_ratio, double max_ratio,
+               int initial_seed);
+
+  int number_of_iterations_;
+  std::vector<FileEntry> file_entries_;
+};
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+#endif  // COBALT_MEDIA_SANDBOX_FUZZER_APP_H_
diff --git a/src/cobalt/media/sandbox/in_memory_data_source.cc b/src/cobalt/media/sandbox/in_memory_data_source.cc
new file mode 100644
index 0000000..9abd0ca
--- /dev/null
+++ b/src/cobalt/media/sandbox/in_memory_data_source.cc
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/media/sandbox/in_memory_data_source.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+InMemoryDataSource::InMemoryDataSource(const std::vector<uint8>& content)
+    : content_(content) {}
+
+void InMemoryDataSource::Read(int64 position, int size, uint8* data,
+                              const ReadCB& read_cb) {
+  DCHECK(data);
+
+  if (position < 0 || size < 0) {
+    read_cb.Run(kInvalidSize);
+    return;
+  }
+
+  uint64 uint64_position = static_cast<uint64>(position);
+
+  if (uint64_position > content_.size() ||
+      uint64_position + size > content_.size()) {
+    read_cb.Run(kInvalidSize);
+    return;
+  }
+
+  if (size == 0) {
+    read_cb.Run(0);
+    return;
+  }
+
+  memcpy(data, &content_[0] + position, size);
+  read_cb.Run(size);
+}
+
+void InMemoryDataSource::Stop(const base::Closure& callback) { callback.Run(); }
+
+bool InMemoryDataSource::GetSize(int64* size_out) {
+  DCHECK(size_out);
+  *size_out = content_.size();
+  return true;
+}
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
diff --git a/src/cobalt/media/sandbox/in_memory_data_source.h b/src/cobalt/media/sandbox/in_memory_data_source.h
new file mode 100644
index 0000000..adfbf42
--- /dev/null
+++ b/src/cobalt/media/sandbox/in_memory_data_source.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_
+#define COBALT_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_
+
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "media/base/data_source.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+// A BufferedDataSource that keeps all its data in memory.  This is used for
+// testing or fuzzing only.
+class InMemoryDataSource : public ::media::DataSource {
+ public:
+  static const int64 kInvalidSize = -1;
+
+  explicit InMemoryDataSource(const std::vector<uint8>& content);
+
+  // DataSource methods.
+  void Read(int64 position, int size, uint8* data,
+            const ReadCB& read_cb) OVERRIDE;
+  void Stop(const base::Closure& callback) OVERRIDE;
+  bool GetSize(int64* size_out) OVERRIDE;
+  bool IsStreaming() OVERRIDE { return false; }
+  void SetBitrate(int bitrate) OVERRIDE { UNREFERENCED_PARAMETER(bitrate); }
+
+ private:
+  std::vector<uint8> content_;
+};
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+#endif  // COBALT_MEDIA_SANDBOX_IN_MEMORY_DATA_SOURCE_H_
diff --git a/src/cobalt/media/sandbox/media_source_demuxer.cc b/src/cobalt/media/sandbox/media_source_demuxer.cc
new file mode 100644
index 0000000..b657f27
--- /dev/null
+++ b/src/cobalt/media/sandbox/media_source_demuxer.cc
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/media/sandbox/media_source_demuxer.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/message_loop.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/demuxer.h"
+#include "media/base/pipeline_status.h"
+#include "media/filters/chunk_demuxer.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+namespace {
+
+using base::Bind;
+using ::media::BindToCurrentLoop;
+using ::media::DecoderBuffer;
+using ::media::DemuxerStream;
+using ::media::ChunkDemuxer;
+
+const char kSourceId[] = "id";
+
+// Stub log function.
+void Log(const std::string& message) { UNREFERENCED_PARAMETER(message); }
+
+// Stub need key callback.
+void NeedKeyCB(const std::string& type, scoped_array<uint8> init_data,
+               int init_data_size) {
+  NOTREACHED();
+}
+
+bool IsMP4(const std::vector<uint8>& content) {
+  return content.size() >= 8 && memcmp(&content[4], "ftyp", 4) == 0;
+}
+
+std::vector<std::string> MakeStringVector(const char* string) {
+  std::vector<std::string> result;
+  result.push_back(string);
+  return result;
+}
+
+bool AddSourceBuffer(bool is_mp4, ChunkDemuxer* demuxer) {
+  const char kMP4Mime[] = "video/mp4";
+  const char kAVCCodecs[] = "avc1.640028";
+  const char kWebMMime[] = "video/webm";
+  const char kVp9Codecs[] = "vp9";
+
+  std::vector<std::string> codecs =
+      MakeStringVector(is_mp4 ? kAVCCodecs : kVp9Codecs);
+  ChunkDemuxer::Status status =
+      demuxer->AddId(kSourceId, is_mp4 ? kMP4Mime : kWebMMime, codecs);
+  CHECK_EQ(status, ChunkDemuxer::kOk);
+  return status == ChunkDemuxer::kOk;
+}
+
+// Helper class to load an adaptive video file and call |append_buffer_cb| for
+// every frame.
+class Loader : public ::media::DemuxerHost {
+ public:
+  typedef base::Callback<void(::media::Buffer*)> AppendBufferCB;
+
+  Loader(const std::vector<uint8>& content,
+         const AppendBufferCB& append_buffer_cb)
+      : valid_(true),
+        ended_(false),
+        append_buffer_cb_(append_buffer_cb),
+        content_(content),
+        offset_(0),
+        read_in_progress_(false) {
+    DCHECK(!append_buffer_cb.is_null());
+
+    demuxer_ = new ChunkDemuxer(
+        BindToCurrentLoop(Bind(&Loader::OnDemuxerOpen, base::Unretained(this),
+                               IsMP4(content))),
+        Bind(NeedKeyCB), Bind(Log));
+    demuxer_->Initialize(
+        this, ::media::BindToCurrentLoop(
+                  Bind(&Loader::OnDemuxerStatus, base::Unretained(this))));
+    while (valid_ && !ended_) {
+      MessageLoop::current()->RunUntilIdle();
+    }
+  }
+
+  bool valid() const { return valid_; }
+  const ::media::VideoDecoderConfig& config() const { return config_; }
+
+ private:
+  void SetTotalBytes(int64 total_bytes) OVERRIDE {
+    UNREFERENCED_PARAMETER(total_bytes);
+  }
+  void AddBufferedByteRange(int64 start, int64 end) OVERRIDE {
+    UNREFERENCED_PARAMETER(start);
+    UNREFERENCED_PARAMETER(end);
+  }
+  void AddBufferedTimeRange(base::TimeDelta start,
+                            base::TimeDelta end) OVERRIDE {
+    UNREFERENCED_PARAMETER(start);
+    UNREFERENCED_PARAMETER(end);
+  }
+
+  void SetDuration(base::TimeDelta duration) OVERRIDE {
+    UNREFERENCED_PARAMETER(duration);
+  }
+  void OnDemuxerError(::media::PipelineStatus error) OVERRIDE {
+    valid_ = false;
+  }
+  void OnDemuxerOpen(bool is_mp4) {
+    valid_ &= AddSourceBuffer(is_mp4, demuxer_);
+    if (!valid_) {
+      return;
+    }
+    ConsumeContent();
+    if (!demuxer_->GetStream(DemuxerStream::VIDEO)) {
+      valid_ = false;
+      return;
+    }
+    while (valid_ && !ended_) {
+      ConsumeContent();
+      ProduceBuffer();
+      MessageLoop::current()->RunUntilIdle();
+    }
+  }
+  void OnDemuxerStatus(::media::PipelineStatus status) {
+    if (status == ::media::PIPELINE_OK) {
+      config_.CopyFrom(
+          demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config());
+    } else {
+      valid_ = false;
+    }
+  }
+  void ConsumeContent() {
+    const float kLowWaterMarkInSeconds = 1.f;
+    const size_t kMaxBytesToAppend = 5 * 1024 * 1024;
+
+    ::media::Ranges<base::TimeDelta> ranges =
+        demuxer_->GetBufferedRanges(kSourceId);
+    if (offset_ < content_.size()) {
+      base::TimeDelta range_end;
+      if (ranges.size() != 0) {
+        range_end = ranges.end(ranges.size() - 1);
+      }
+      if ((range_end - timestamp_of_last_buffer_).InSecondsF() >
+          kLowWaterMarkInSeconds) {
+        return;
+      }
+      size_t bytes_to_append =
+          std::min(kMaxBytesToAppend, content_.size() - offset_);
+      demuxer_->AppendData(kSourceId, &content_[0] + offset_, bytes_to_append);
+      offset_ += bytes_to_append;
+    }
+    if (offset_ == content_.size()) {
+      demuxer_->EndOfStream(::media::PIPELINE_OK);
+      ++offset_;
+    }
+  }
+  void ProduceBuffer() {
+    if (!read_in_progress_) {
+      read_in_progress_ = true;
+      demuxer_->GetStream(DemuxerStream::VIDEO)
+          ->Read(Bind(&Loader::OnDemuxerRead, base::Unretained(this)));
+    }
+  }
+  void OnDemuxerRead(DemuxerStream::Status status,
+                     const scoped_refptr<DecoderBuffer>& buffer) {
+    // This should only happen during seeking which won't happen to this class.
+    DCHECK_NE(status, DemuxerStream::kAborted);
+    if (status == DemuxerStream::kConfigChanged) {
+      config_.CopyFrom(
+          demuxer_->GetStream(DemuxerStream::VIDEO)->video_decoder_config());
+      ProduceBuffer();
+      return;
+    }
+    DCHECK_EQ(status, DemuxerStream::kOk);
+    if (buffer->IsEndOfStream()) {
+      ended_ = true;
+    } else {
+      timestamp_of_last_buffer_ = buffer->GetTimestamp();
+      append_buffer_cb_.Run(buffer);
+    }
+    read_in_progress_ = false;
+  }
+
+  bool valid_;
+  bool ended_;
+  AppendBufferCB append_buffer_cb_;
+  const std::vector<uint8>& content_;
+  size_t offset_;
+  bool read_in_progress_;
+  base::TimeDelta timestamp_of_last_buffer_;
+  scoped_refptr<ChunkDemuxer> demuxer_;
+  ::media::VideoDecoderConfig config_;
+};
+
+}  // namespace
+
+MediaSourceDemuxer::MediaSourceDemuxer(const std::vector<uint8>& content)
+    : valid_(true) {
+  Loader loader(
+      content, Bind(&MediaSourceDemuxer::AppendBuffer, base::Unretained(this)));
+  valid_ = loader.valid();
+  if (valid_) {
+    config_.CopyFrom(loader.config());
+  } else {
+    au_data_.clear();
+    descs_.clear();
+  }
+}
+
+void MediaSourceDemuxer::AppendBuffer(::media::Buffer* buffer) {
+  AUDescriptor desc = {0};
+  desc.offset = au_data_.size();
+  desc.size = buffer->GetDataSize();
+  desc.timestamp = buffer->GetTimestamp();
+
+  au_data_.insert(au_data_.end(), buffer->GetData(),
+                  buffer->GetData() + buffer->GetDataSize());
+  descs_.push_back(desc);
+}
+
+const MediaSourceDemuxer::AUDescriptor& MediaSourceDemuxer::GetFrame(
+    size_t index) const {
+  DCHECK_LT(index, descs_.size());
+
+  return descs_[index];
+}
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
diff --git a/src/cobalt/media/sandbox/media_source_demuxer.h b/src/cobalt/media/sandbox/media_source_demuxer.h
new file mode 100644
index 0000000..f86679a
--- /dev/null
+++ b/src/cobalt/media/sandbox/media_source_demuxer.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_
+#define COBALT_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/time.h"
+#include "media/base/buffers.h"
+#include "media/base/video_decoder_config.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+// This class turns a buffer containing a whole media source file into AUs.
+class MediaSourceDemuxer {
+ public:
+  struct AUDescriptor {
+    size_t offset;
+    size_t size;
+    base::TimeDelta timestamp;
+  };
+
+  explicit MediaSourceDemuxer(const std::vector<uint8>& content);
+
+  bool valid() const { return valid_; }
+
+  size_t GetFrameCount() const { return descs_.size(); }
+  const AUDescriptor& GetFrame(size_t index) const;
+  const std::vector<uint8>& au_data() const { return au_data_; }
+
+  const ::media::VideoDecoderConfig& config() const { return config_; }
+
+ private:
+  void AppendBuffer(::media::Buffer* buffer);
+
+  bool valid_;
+  std::vector<uint8> au_data_;
+  std::vector<AUDescriptor> descs_;
+  ::media::VideoDecoderConfig config_;
+};
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+#endif  // COBALT_MEDIA_SANDBOX_MEDIA_SOURCE_DEMUXER_H_
diff --git a/src/cobalt/media/sandbox/media_source_sandbox.cc b/src/cobalt/media/sandbox/media_source_sandbox.cc
index 74e528b..07861b8 100644
--- a/src/cobalt/media/sandbox/media_source_sandbox.cc
+++ b/src/cobalt/media/sandbox/media_source_sandbox.cc
@@ -18,6 +18,8 @@
 #include <string>
 #include <vector>
 
+#include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/memory/ref_counted.h"
 #include "base/message_loop.h"
@@ -26,6 +28,7 @@
 #include "cobalt/base/wrap_main.h"
 #include "cobalt/media/sandbox/media_sandbox.h"
 #include "cobalt/media/sandbox/web_media_player_helper.h"
+#include "cobalt/render_tree/image.h"
 #include "media/base/video_frame.h"
 #include "net/base/net_util.h"
 
@@ -35,9 +38,11 @@
 namespace {
 
 typedef ::media::WebMediaPlayer::AddIdStatus AddIdStatus;
+
 using base::TimeDelta;
 using ::media::VideoFrame;
 using ::media::WebMediaPlayer;
+using render_tree::Image;
 
 GURL ResolveUrl(const char* arg) {
   GURL video_url(arg);
@@ -137,6 +142,14 @@
   }
 }
 
+scoped_refptr<Image> FrameCB(WebMediaPlayerHelper* player_helper,
+                             const base::TimeDelta& time) {
+  UNREFERENCED_PARAMETER(time);
+
+  scoped_refptr<VideoFrame> frame = player_helper->GetCurrentFrame();
+  return frame ? reinterpret_cast<Image*>(frame->texture_id()) : NULL;
+}
+
 int SandboxMain(int argc, char** argv) {
   if (argc != 3 && argc != 4) {
     LOG(ERROR) << "Usage: " << argv[0]
@@ -198,6 +211,9 @@
 
   scoped_refptr<VideoFrame> last_frame;
 
+  media_sandbox.RegisterFrameCB(
+      base::Bind(FrameCB, base::Unretained(&player_helper)));
+
   for (;;) {
     AppendData(kAudioId, audio_loader.buffer(), &audio_offset, player);
     AppendData(kVideoId, video_loader.buffer(), &video_offset, player);
@@ -211,7 +227,7 @@
       break;
     }
     scoped_refptr<VideoFrame> frame = player_helper.GetCurrentFrame();
-    if (frame != last_frame) {
+    if (frame && frame != last_frame) {
       LOG(INFO) << "showing frame " << frame->GetTimestamp().InMicroseconds();
       last_frame = frame;
     }
diff --git a/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc
new file mode 100644
index 0000000..b5ab128
--- /dev/null
+++ b/src/cobalt/media/sandbox/raw_video_decoder_fuzzer.cc
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <map>
+#include <vector>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/time.h"
+#include "cobalt/base/wrap_main.h"
+#include "cobalt/media/sandbox/fuzzer_app.h"
+#include "cobalt/media/sandbox/media_sandbox.h"
+#include "cobalt/media/sandbox/media_source_demuxer.h"
+#include "cobalt/media/sandbox/zzuf_fuzzer.h"
+#include "media/base/bind_to_loop.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+namespace {
+
+using base::Time;
+using ::media::BindToCurrentLoop;
+using ::media::DecoderBuffer;
+using ::media::ShellRawVideoDecoder;
+using ::media::VideoFrame;
+
+class VideoDecoderFuzzer {
+ public:
+  VideoDecoderFuzzer(const std::vector<uint8_t>& au_data,
+                     MediaSourceDemuxer* demuxer, ShellRawVideoDecoder* decoder)
+      : au_data_(au_data),
+        demuxer_(demuxer),
+        decoder_(decoder),
+        au_index_(0),
+        error_occured_(false),
+        eos_decoded_(false) {}
+
+  void Fuzz() {
+    UpdateCurrentAUBuffer();
+    decoder_->Decode(current_au_buffer_, BindToCurrentLoop(base::Bind(
+                                             &VideoDecoderFuzzer::FrameDecoded,
+                                             base::Unretained(this))));
+    MessageLoop::current()->RunUntilIdle();
+    DCHECK(IsEnded());
+  }
+
+ private:
+  void UpdateCurrentAUBuffer() {
+    if (au_index_ < demuxer_->GetFrameCount()) {
+      MediaSourceDemuxer::AUDescriptor desc = demuxer_->GetFrame(au_index_);
+      current_au_buffer_ =
+          ::media::ShellBufferFactory::Instance()->AllocateBufferNow(desc.size);
+      memcpy(current_au_buffer_->GetWritableData(), &au_data_[0] + desc.offset,
+             desc.size);
+      ++au_index_;
+    } else if (!current_au_buffer_->IsEndOfStream()) {
+      current_au_buffer_ =
+          DecoderBuffer::CreateEOSBuffer(::media::kNoTimestamp());
+    }
+  }
+  void FrameDecoded(ShellRawVideoDecoder::DecodeStatus status,
+                    const scoped_refptr<VideoFrame>& frame) {
+    if (frame) {
+      last_frame_decoded_time_ = Time::Now();
+      if (frame->IsEndOfStream()) {
+        eos_decoded_ = true;
+      }
+    }
+    switch (status) {
+      case ShellRawVideoDecoder::FRAME_DECODED:
+      case ShellRawVideoDecoder::NEED_MORE_DATA:
+        UpdateCurrentAUBuffer();
+        break;
+      case ShellRawVideoDecoder::FATAL_ERROR:
+        error_occured_ = true;
+        // Even if there is a fatal error, we still want to keep sending the
+        // rest buffers to decoder.
+        UpdateCurrentAUBuffer();
+        break;
+      case ShellRawVideoDecoder::RETRY_WITH_SAME_BUFFER:
+        if (current_au_buffer_->IsEndOfStream() &&
+            (Time::Now() - last_frame_decoded_time_).InMilliseconds() > 500) {
+          error_occured_ = true;
+        }
+        break;
+    }
+    if (!IsEnded()) {
+      decoder_->Decode(
+          current_au_buffer_,
+          BindToCurrentLoop(base::Bind(&VideoDecoderFuzzer::FrameDecoded,
+                                       base::Unretained(this))));
+    }
+  }
+  bool IsEnded() const {
+    if (error_occured_) return true;
+    return eos_decoded_ ||
+           (error_occured_ && current_au_buffer_->IsEndOfStream());
+  }
+
+  const std::vector<uint8_t>& au_data_;
+  MediaSourceDemuxer* demuxer_;
+  ShellRawVideoDecoder* decoder_;
+  size_t au_index_;
+  scoped_refptr<DecoderBuffer> current_au_buffer_;
+  bool error_occured_;
+  bool eos_decoded_;
+  Time last_frame_decoded_time_;
+};
+
+int CalculateCheckSum(const std::vector<uint8>& data) {
+  int checksum = 0;
+  for (size_t i = 0; i < data.size(); ++i) {
+    checksum += data[i];
+  }
+  return checksum;
+}
+
+// This function replace the original data inside the original file with the
+// fuzzed data to created a valid container with fuzzed AUs.  |filename| should
+// contain a file that inside a path readable by the host.
+void DumpFuzzedData(const std::string& filename, std::vector<uint8> container,
+                    const MediaSourceDemuxer& demuxer,
+                    const ZzufFuzzer& fuzzer) {
+  std::vector<uint8>::iterator last_found = container.begin();
+  for (size_t i = 0; i < demuxer.GetFrameCount(); ++i) {
+    MediaSourceDemuxer::AUDescriptor desc = demuxer.GetFrame(i);
+    std::vector<uint8>::const_iterator begin =
+        demuxer.au_data().begin() + desc.offset;
+    std::vector<uint8>::const_iterator end = begin + desc.size;
+    std::vector<uint8>::iterator offset =
+        std::search(last_found, container.end(), begin, end);
+    std::copy(fuzzer.GetFuzzedContent().begin() + desc.offset,
+              fuzzer.GetFuzzedContent().begin() + desc.offset + desc.size,
+              offset);
+    last_found = offset + desc.size + 1;
+  }
+  file_util::WriteFile(FilePath(filename),
+                       reinterpret_cast<const char*>(&container[0]),
+                       container.size());
+}
+
+class RawVideoDecoderFuzzerApp : public FuzzerApp {
+ public:
+  explicit RawVideoDecoderFuzzerApp(MediaSandbox* media_sandbox)
+      : media_sandbox_(media_sandbox) {}
+  ~RawVideoDecoderFuzzerApp() {
+    while (!demuxers_.empty()) {
+      delete demuxers_.begin()->second;
+      demuxers_.erase(demuxers_.begin());
+    }
+  }
+
+  std::vector<uint8> ParseFileContent(
+      const std::string& file_name,
+      const std::vector<uint8>& file_content) OVERRIDE {
+    std::string ext = FilePath(file_name).Extension();
+    if (ext != ".webm" && ext != ".mp4") {
+      LOG(ERROR) << "Skip unsupported file " << file_name;
+      return std::vector<uint8>();
+    }
+
+    scoped_ptr<MediaSourceDemuxer> demuxer(new MediaSourceDemuxer(
+        std::vector<uint8>(file_content.begin(), file_content.end())));
+    if (demuxer->valid() && demuxer->GetFrameCount() > 0) {
+      demuxers_[file_name] = demuxer.release();
+      return demuxers_[file_name]->au_data();
+    }
+    LOG(ERROR) << "Failed to demux video: " << file_name;
+    return std::vector<uint8>();
+  }
+
+  void Fuzz(const std::string& file_name,
+            const std::vector<uint8>& fuzzing_content) OVERRIDE {
+    DCHECK(demuxers_.find(file_name) != demuxers_.end());
+    MediaSourceDemuxer* demuxer = demuxers_[file_name];
+    scoped_ptr<ShellRawVideoDecoder> decoder =
+        media_sandbox_->GetMediaModule()->GetRawVideoDecoderFactory()->Create(
+            demuxer->config(), NULL, false);
+    DCHECK(decoder);
+    VideoDecoderFuzzer decoder_fuzzer(fuzzing_content, demuxer, decoder.get());
+    decoder_fuzzer.Fuzz();
+  }
+
+ private:
+  MediaSandbox* media_sandbox_;
+  std::map<std::string, MediaSourceDemuxer*> demuxers_;
+};
+
+int SandboxMain(int argc, char** argv) {
+  MediaSandbox media_sandbox(
+      argc, argv, FilePath(FILE_PATH_LITERAL("raw_video_decoder_fuzzer.json")));
+  RawVideoDecoderFuzzerApp fuzzer_app(&media_sandbox);
+
+  if (fuzzer_app.Init(argc, argv)) {
+    fuzzer_app.RunFuzzingLoop();
+  }
+
+  return 0;
+}
+
+}  // namespace
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
diff --git a/src/cobalt/media/sandbox/sandbox.gyp b/src/cobalt/media/sandbox/sandbox.gyp
index 8c055c4..3290d35 100644
--- a/src/cobalt/media/sandbox/sandbox.gyp
+++ b/src/cobalt/media/sandbox/sandbox.gyp
@@ -16,6 +16,9 @@
 # media/renderer interface.
 
 {
+  'variables': {
+    'has_zzuf': '<!(python ../../../build/dir_exists.py ../../../third_party/zzuf)',
+  },
   'targets': [
     # This target will build a sandbox application that allows for easy
     # experimentation with the media interface on any platform.  This can
@@ -54,7 +57,7 @@
       'variables': {
         'executable_name': 'web_media_player_sandbox',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
 
     # This target will build a sandbox application that allows for easy
@@ -65,9 +68,9 @@
       'sources': [
         'media_sandbox.cc',
         'media_sandbox.h',
+        'media_source_sandbox.cc',
         'web_media_player_helper.cc',
         'web_media_player_helper.h',
-        'media_source_sandbox.cc',
       ],
       'dependencies': [
         '<(DEPTH)/cobalt/base/base.gyp:base',
@@ -92,7 +95,98 @@
       'variables': {
         'executable_name': 'media_source_sandbox',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
   ],
+  'conditions': [
+    ['OS == "starboard" and has_zzuf == "True"', {
+      'targets': [
+        # This target will build a sandbox application that allows for fuzzing
+        # decoder.
+        {
+          'target_name': 'raw_video_decoder_fuzzer',
+          'type': '<(final_executable_type)',
+          'sources': [
+            'fuzzer_app.cc',
+            'fuzzer_app.h',
+            'media_sandbox.cc',
+            'media_sandbox.h',
+            'media_source_demuxer.cc',
+            'media_source_demuxer.h',
+            'raw_video_decoder_fuzzer.cc',
+            'zzuf_fuzzer.cc',
+            'zzuf_fuzzer.h',
+          ],
+          'dependencies': [
+            '<(DEPTH)/cobalt/base/base.gyp:base',
+            # Use test data from browser to avoid keeping two copies of video files.
+            '<(DEPTH)/cobalt/browser/browser.gyp:browser_copy_test_data',
+            '<(DEPTH)/cobalt/loader/loader.gyp:loader',
+            '<(DEPTH)/cobalt/media/media.gyp:media',
+            '<(DEPTH)/cobalt/network/network.gyp:network',
+            '<(DEPTH)/cobalt/renderer/renderer.gyp:renderer',
+            '<(DEPTH)/cobalt/system_window/system_window.gyp:system_window',
+            '<(DEPTH)/cobalt/trace_event/trace_event.gyp:trace_event',
+            '<(DEPTH)/googleurl/googleurl.gyp:googleurl',
+            '<(DEPTH)/third_party/zzuf/zzuf.gyp:zzuf',
+          ],
+        },
+
+        {
+          'target_name': 'raw_video_decoder_fuzzer_deploy',
+          'type': 'none',
+          'dependencies': [
+            'raw_video_decoder_fuzzer',
+          ],
+          'variables': {
+            'executable_name': 'raw_video_decoder_fuzzer',
+          },
+          'includes': [ '../../../starboard/build/deploy.gypi' ],
+        },
+
+        # This target will build a sandbox application that allows for fuzzing
+        # shell demuxers.
+        {
+          'target_name': 'shell_demuxer_fuzzer',
+          'type': '<(final_executable_type)',
+          'sources': [
+            'fuzzer_app.cc',
+            'fuzzer_app.h',
+            'in_memory_data_source.cc',
+            'in_memory_data_source.h',
+            'media_sandbox.cc',
+            'media_sandbox.h',
+            'shell_demuxer_fuzzer.cc',
+            'zzuf_fuzzer.cc',
+            'zzuf_fuzzer.h',
+          ],
+          'dependencies': [
+            '<(DEPTH)/cobalt/base/base.gyp:base',
+            # Use test data from browser to avoid keeping two copies of video files.
+            '<(DEPTH)/cobalt/browser/browser.gyp:browser_copy_test_data',
+            '<(DEPTH)/cobalt/loader/loader.gyp:loader',
+            '<(DEPTH)/cobalt/media/media.gyp:media',
+            '<(DEPTH)/cobalt/network/network.gyp:network',
+            '<(DEPTH)/cobalt/renderer/renderer.gyp:renderer',
+            '<(DEPTH)/cobalt/system_window/system_window.gyp:system_window',
+            '<(DEPTH)/cobalt/trace_event/trace_event.gyp:trace_event',
+            '<(DEPTH)/googleurl/googleurl.gyp:googleurl',
+            '<(DEPTH)/third_party/zzuf/zzuf.gyp:zzuf',
+          ],
+        },
+
+        {
+          'target_name': 'shell_demuxer_fuzzer_deploy',
+          'type': 'none',
+          'dependencies': [
+            'shell_demuxer_fuzzer',
+          ],
+          'variables': {
+            'executable_name': 'shell_demuxer_fuzzer',
+          },
+          'includes': [ '../../../starboard/build/deploy.gypi' ],
+        },
+      ],
+    }],
+  ],
 }
diff --git a/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc b/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc
new file mode 100644
index 0000000..c469c5c
--- /dev/null
+++ b/src/cobalt/media/sandbox/shell_demuxer_fuzzer.cc
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/compiler_specific.h"
+#include "base/file_path.h"
+#include "base/memory/ref_counted.h"
+#include "cobalt/base/wrap_main.h"
+#include "cobalt/media/sandbox/fuzzer_app.h"
+#include "cobalt/media/sandbox/in_memory_data_source.h"
+#include "cobalt/media/sandbox/media_sandbox.h"
+#include "media/base/bind_to_loop.h"
+#include "media/base/pipeline_status.h"
+#include "media/filters/shell_demuxer.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+namespace {
+
+using base::Bind;
+using ::media::BindToCurrentLoop;
+using ::media::DecoderBuffer;
+using ::media::Demuxer;
+using ::media::DemuxerHost;
+using ::media::DemuxerStream;
+using ::media::PipelineStatus;
+using ::media::ShellDemuxer;
+
+class ShellDemuxerFuzzer : DemuxerHost {
+ public:
+  explicit ShellDemuxerFuzzer(const std::vector<uint8>& content)
+      : error_occurred_(false), eos_count_(0), stopped_(false) {
+    demuxer_ = new ShellDemuxer(base::MessageLoopProxy::current(),
+                                new InMemoryDataSource(content));
+  }
+
+  void Fuzz() {
+    demuxer_->Initialize(
+        this, Bind(&ShellDemuxerFuzzer::InitializeCB, base::Unretained(this)));
+
+    // Check if there is any error or if both of the audio and video streams
+    // have reached eos.
+    while (!error_occurred_ && eos_count_ != 2) {
+      MessageLoop::current()->RunUntilIdle();
+    }
+
+    demuxer_->Stop(Bind(&ShellDemuxerFuzzer::StopCB, base::Unretained(this)));
+
+    while (!stopped_) {
+      MessageLoop::current()->RunUntilIdle();
+    }
+  }
+
+ private:
+  // DataSourceHost methods (parent class of DemuxerHost)
+  void SetTotalBytes(int64 total_bytes) OVERRIDE {
+    UNREFERENCED_PARAMETER(total_bytes);
+  }
+
+  void AddBufferedByteRange(int64 start, int64 end) OVERRIDE {
+    UNREFERENCED_PARAMETER(start);
+    UNREFERENCED_PARAMETER(end);
+  }
+
+  void AddBufferedTimeRange(base::TimeDelta start,
+                            base::TimeDelta end) OVERRIDE {
+    UNREFERENCED_PARAMETER(start);
+    UNREFERENCED_PARAMETER(end);
+  }
+
+  // DemuxerHost methods
+  void SetDuration(base::TimeDelta duration) OVERRIDE {
+    UNREFERENCED_PARAMETER(duration);
+  }
+  void OnDemuxerError(PipelineStatus error) OVERRIDE {
+    UNREFERENCED_PARAMETER(error);
+    error_occurred_ = true;
+  }
+
+  void InitializeCB(PipelineStatus status) {
+    DCHECK(!error_occurred_);
+    if (status != ::media::PIPELINE_OK) {
+      error_occurred_ = true;
+      return;
+    }
+    scoped_refptr<DemuxerStream> audio_stream =
+        demuxer_->GetStream(DemuxerStream::AUDIO);
+    scoped_refptr<DemuxerStream> video_stream =
+        demuxer_->GetStream(DemuxerStream::VIDEO);
+    if (!audio_stream || !video_stream ||
+        !audio_stream->audio_decoder_config().IsValidConfig() ||
+        !video_stream->video_decoder_config().IsValidConfig()) {
+      error_occurred_ = true;
+      return;
+    }
+    audio_stream->Read(BindToCurrentLoop(Bind(
+        &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), audio_stream)));
+    video_stream->Read(BindToCurrentLoop(Bind(
+        &ShellDemuxerFuzzer::ReadCB, base::Unretained(this), video_stream)));
+  }
+
+  void StopCB() { stopped_ = true; }
+
+  void ReadCB(const scoped_refptr<DemuxerStream>& stream,
+              DemuxerStream::Status status,
+              const scoped_refptr<DecoderBuffer>& buffer) {
+    DCHECK_NE(status, DemuxerStream::kAborted);
+    if (status == DemuxerStream::kOk) {
+      DCHECK(buffer);
+      if (buffer->IsEndOfStream()) {
+        ++eos_count_;
+        return;
+      }
+    }
+    DCHECK(!error_occurred_);
+    stream->Read(BindToCurrentLoop(
+        Bind(&ShellDemuxerFuzzer::ReadCB, base::Unretained(this), stream)));
+  }
+
+  bool error_occurred_;
+  int eos_count_;
+  bool stopped_;
+  scoped_refptr<ShellDemuxer> demuxer_;
+};
+
+class ShellDemuxerFuzzerApp : public FuzzerApp {
+ public:
+  explicit ShellDemuxerFuzzerApp(MediaSandbox* media_sandbox)
+      : media_sandbox_(media_sandbox) {}
+
+  std::vector<uint8> ParseFileContent(
+      const std::string& file_name,
+      const std::vector<uint8>& file_content) OVERRIDE {
+    std::string ext = FilePath(file_name).Extension();
+    if (ext != ".flv" && ext != ".mp4") {
+      LOG(ERROR) << "Skip unsupported file " << file_name;
+      return std::vector<uint8>();
+    }
+    return file_content;
+  }
+
+  void Fuzz(const std::string& file_name,
+            const std::vector<uint8>& fuzzing_content) OVERRIDE {
+    ShellDemuxerFuzzer demuxer_fuzzer(fuzzing_content);
+    demuxer_fuzzer.Fuzz();
+  }
+
+ private:
+  MediaSandbox* media_sandbox_;
+};
+
+int SandboxMain(int argc, char** argv) {
+  MediaSandbox media_sandbox(
+      argc, argv, FilePath(FILE_PATH_LITERAL("shell_demuxer_fuzzer.json")));
+  ShellDemuxerFuzzerApp fuzzer_app(&media_sandbox);
+
+  if (fuzzer_app.Init(argc, argv)) {
+    fuzzer_app.RunFuzzingLoop();
+  }
+
+  return 0;
+}
+
+}  // namespace
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+COBALT_WRAP_SIMPLE_MAIN(cobalt::media::sandbox::SandboxMain);
diff --git a/src/cobalt/media/sandbox/zzuf_fuzzer.cc b/src/cobalt/media/sandbox/zzuf_fuzzer.cc
new file mode 100644
index 0000000..bb52fa7
--- /dev/null
+++ b/src/cobalt/media/sandbox/zzuf_fuzzer.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/media/sandbox/zzuf_fuzzer.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+ZzufFuzzer::ZzufFuzzer(const std::vector<uint8>& original_content,
+                       double min_ratio, double max_ratio,
+                       int initial_seed /*= kSeedForOriginalContent*/)
+    : seed_(initial_seed) {
+  original_content_.assign(original_content.begin(), original_content.end());
+  DCHECK(!original_content_.empty());
+
+  _zz_fd_init();
+  zzuf_set_ratio(min_ratio, max_ratio);
+
+  UpdateFuzzedContent();
+}
+
+ZzufFuzzer::~ZzufFuzzer() { _zz_fd_fini(); }
+
+void ZzufFuzzer::AdvanceSeed() {
+  ++seed_;
+  UpdateFuzzedContent();
+}
+
+void ZzufFuzzer::UpdateFuzzedContent() {
+  // Because zzuf is not actually doing any io, the fd just serves as an index
+  // to its fd to fuzz context map.
+  static const int kFd = 0;
+
+  if (seed_ == kSeedForOriginalContent) {
+    fuzzed_content_ = original_content_;
+    return;
+  }
+
+  fuzzed_content_ = original_content_;
+
+  zzuf_set_seed(seed_);
+
+  _zz_register(kFd);
+  _zz_fuzz(kFd, &fuzzed_content_[0], fuzzed_content_.size());
+  _zz_unregister(kFd);
+}
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
diff --git a/src/cobalt/media/sandbox/zzuf_fuzzer.h b/src/cobalt/media/sandbox/zzuf_fuzzer.h
new file mode 100644
index 0000000..6020b22
--- /dev/null
+++ b/src/cobalt/media/sandbox/zzuf_fuzzer.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_MEDIA_SANDBOX_ZZUF_FUZZER_H_
+#define COBALT_MEDIA_SANDBOX_ZZUF_FUZZER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+
+extern "C" {
+#include "third_party/zzuf/src/common/fd.h"
+#include "third_party/zzuf/src/common/fuzz.h"
+}
+
+namespace cobalt {
+namespace media {
+namespace sandbox {
+
+// This class provide fuzzed content based on the original content and a seed
+// that can be advanced.  By default the first fuzzed content it returns is the
+// same as the original content.
+class ZzufFuzzer {
+ public:
+  static const int kSeedForOriginalContent = -1;
+
+  // |initial_seed| can be used to "fast-forward" to the particular seed that
+  // generates the data to cause an issue.  During normal fuzzing this should be
+  // left to its default argument to ensure that it covers the original data.
+  ZzufFuzzer(const std::vector<uint8>& original_content, double min_ratio,
+             double max_ratio, int initial_seed = kSeedForOriginalContent);
+  ~ZzufFuzzer();
+
+  int seed() const { return seed_; }
+  const std::vector<uint8_t>& GetOriginalContent() const {
+    return original_content_;
+  }
+  const std::vector<uint8_t>& GetFuzzedContent() const {
+    return fuzzed_content_;
+  }
+
+  void AdvanceSeed();
+
+ private:
+  void UpdateFuzzedContent();
+
+  int seed_;
+  std::vector<uint8_t> original_content_;
+  std::vector<uint8_t> fuzzed_content_;
+};
+
+}  // namespace sandbox
+}  // namespace media
+}  // namespace cobalt
+
+#endif  // COBALT_MEDIA_SANDBOX_ZZUF_FUZZER_H_
diff --git a/src/cobalt/media/shell_video_data_allocator_common.cc b/src/cobalt/media/shell_video_data_allocator_common.cc
index 221119b..be0107b 100644
--- a/src/cobalt/media/shell_video_data_allocator_common.cc
+++ b/src/cobalt/media/shell_video_data_allocator_common.cc
@@ -34,10 +34,12 @@
 using cobalt::render_tree::kPixelFormatRGBA8;
 using cobalt::render_tree::MultiPlaneImageDataDescriptor;
 using cobalt::render_tree::ResourceProvider;
+using cobalt::render_tree::kMultiPlaneImageFormatYUV2PlaneBT709;
 using cobalt::render_tree::kMultiPlaneImageFormatYUV3PlaneBT709;
 using cobalt::render_tree::kPixelFormatU8;
 using cobalt::render_tree::kPixelFormatV8;
 using cobalt::render_tree::kPixelFormatY8;
+using cobalt::render_tree::kPixelFormatUV8;
 
 namespace {
 void ReleaseImage(scoped_refptr<Image> /* image */) {}
@@ -76,35 +78,35 @@
   scoped_refptr<FrameBufferCommon> frame_buffer_common =
       base::polymorphic_downcast<FrameBufferCommon*>(frame_buffer.get());
 
+  DCHECK_LE(frame_buffer->data(), param.y_data());
+  DCHECK_LE(param.y_data() + param.y_pitch() * param.decoded_height(),
+            param.u_data());
+  DCHECK_LE(param.u_data() + param.uv_pitch() * param.decoded_height() / 2,
+            param.v_data());
+  DCHECK_LE(param.v_data() + param.uv_pitch() * param.decoded_height() / 2,
+            frame_buffer->data() + frame_buffer->size());
+
   // TODO: Ensure it work with visible_rect with non-zero left and
   // top.  Note that simply add offset to the image buffer may cause alignment
   // issues.
-  gfx::Size decoded_size(param.decoded_width(), param.decoded_height());
   gfx::Size visible_size(param.visible_rect().size());
 
-  intptr_t offset = 0;
-  int pitch_in_bytes = decoded_size.width();
-
-  DCHECK_EQ(pitch_in_bytes % 2, 0) << pitch_in_bytes << " has to be even.";
-
   // Create image data descriptor for the frame in I420.
   MultiPlaneImageDataDescriptor descriptor(
       kMultiPlaneImageFormatYUV3PlaneBT709);
   descriptor.AddPlane(
-      offset, ImageDataDescriptor(visible_size, kPixelFormatY8,
-                                  kAlphaFormatUnpremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height();
+      param.y_data() - frame_buffer->data(),
+      ImageDataDescriptor(visible_size, kPixelFormatY8,
+                          kAlphaFormatUnpremultiplied, param.y_pitch()));
   visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2);
-  pitch_in_bytes /= 2;
   descriptor.AddPlane(
-      offset, ImageDataDescriptor(visible_size, kPixelFormatU8,
-                                  kAlphaFormatUnpremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height() / 2;
+      param.u_data() - frame_buffer->data(),
+      ImageDataDescriptor(visible_size, kPixelFormatU8,
+                          kAlphaFormatUnpremultiplied, param.uv_pitch()));
   descriptor.AddPlane(
-      offset, ImageDataDescriptor(visible_size, kPixelFormatV8,
-                                  kAlphaFormatUnpremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height() / 2;
-  CHECK_EQ(offset, param.decoded_width() * param.decoded_height() * 3 / 2);
+      param.v_data() - frame_buffer->data(),
+      ImageDataDescriptor(visible_size, kPixelFormatV8,
+                          kAlphaFormatUnpremultiplied, param.uv_pitch()));
 
   scoped_refptr<Image> image =
       resource_provider_->CreateMultiPlaneImageFromRawMemory(
@@ -128,32 +130,26 @@
   // TODO: Ensure it work with visible_rect with non-zero left and
   // top.  Note that simply add offset to the image buffer may cause alignment
   // issues.
-  gfx::Size decoded_size(param.decoded_width(), param.decoded_height());
   gfx::Size visible_size(param.visible_rect().size());
 
   intptr_t offset = 0;
-  int pitch_in_bytes = decoded_size.width();
+  int pitch_in_bytes = param.y_pitch();
 
   DCHECK_EQ(pitch_in_bytes % 2, 0) << pitch_in_bytes << " has to be even.";
 
-  // Create image data descriptor for the frame in I420.
+  // Create image data descriptor for the frame in NV12.
   MultiPlaneImageDataDescriptor descriptor(
-      kMultiPlaneImageFormatYUV3PlaneBT709);
+      kMultiPlaneImageFormatYUV2PlaneBT709);
   descriptor.AddPlane(
       offset, ImageDataDescriptor(visible_size, kPixelFormatY8,
                                   kAlphaFormatPremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height();
+  offset += pitch_in_bytes * param.decoded_height();
   visible_size.SetSize(visible_size.width() / 2, visible_size.height() / 2);
-  pitch_in_bytes /= 2;
   descriptor.AddPlane(
-      offset, ImageDataDescriptor(visible_size, kPixelFormatU8,
+      offset, ImageDataDescriptor(visible_size, kPixelFormatUV8,
                                   kAlphaFormatPremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height() / 2;
-  descriptor.AddPlane(
-      offset, ImageDataDescriptor(visible_size, kPixelFormatV8,
-                                  kAlphaFormatPremultiplied, pitch_in_bytes));
-  offset += pitch_in_bytes * decoded_size.height() / 2;
-  CHECK_EQ(offset, param.decoded_width() * param.decoded_height() * 3 / 2);
+  offset += pitch_in_bytes * param.decoded_height() / 2;
+  DCHECK_EQ(offset, pitch_in_bytes * param.decoded_height() * 3 / 2);
 
   scoped_refptr<Image> image =
       resource_provider_->CreateMultiPlaneImageFromRawMemory(
diff --git a/src/cobalt/network/network.gyp b/src/cobalt/network/network.gyp
index 3324a9c..1cbcb99 100644
--- a/src/cobalt/network/network.gyp
+++ b/src/cobalt/network/network.gyp
@@ -123,7 +123,7 @@
       'variables': {
         'executable_name': 'network_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/network/persistent_cookie_store_test.cc b/src/cobalt/network/persistent_cookie_store_test.cc
index ba935a3..7d2762b 100644
--- a/src/cobalt/network/persistent_cookie_store_test.cc
+++ b/src/cobalt/network/persistent_cookie_store_test.cc
@@ -18,9 +18,9 @@
 
 #include <vector>
 
-#include "base/message_loop.h"
 #include "base/file_path.h"
 #include "base/file_util.h"
+#include "base/message_loop.h"
 #include "base/path_service.h"
 #include "base/stringprintf.h"
 #include "base/time.h"
@@ -28,8 +28,8 @@
 #include "cobalt/storage/savegame.h"
 #include "cobalt/storage/savegame_fake.h"
 #include "cobalt/storage/storage_manager.h"
-#include "net/cookies/canonical_cookie.h"
 #include "googleurl/src/gurl.h"
+#include "net/cookies/canonical_cookie.h"
 #include "sql/connection.h"
 #include "sql/statement.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -58,7 +58,7 @@
   CallbackWaiter() : was_called_event_(true, false) {}
   virtual ~CallbackWaiter() {}
   bool TimedWait() {
-    return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500));
+    return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5));
   }
 
  protected:
@@ -120,7 +120,6 @@
   DISALLOW_COPY_AND_ASSIGN(CookieVerifier);
 };
 
-
 std::string GetSavePath() {
   FilePath test_path;
   CHECK(PathService::Get(paths::DIR_COBALT_TEST_OUT, &test_path));
diff --git a/src/cobalt/render_tree/font_provider.h b/src/cobalt/render_tree/font_provider.h
index 7c47a50..c5a3380 100644
--- a/src/cobalt/render_tree/font_provider.h
+++ b/src/cobalt/render_tree/font_provider.h
@@ -28,10 +28,10 @@
 // character based upon what it considers to be the best match.
 class FontProvider {
  public:
-  // Returns a font-glyph combination based upon a passed in character. The
-  // returned font is guaranteed to be non-NULL. However, the glyph index may
-  // be set to |kInvalidGlyphIndex| if no font is found that supports the
-  // requested character.
+  // Returns the font-glyph combination that the FontProvider considers to be
+  // the best match for the passed in character. The returned font is guaranteed
+  // to be non-NULL. However, the glyph index may be set to |kInvalidGlyphIndex|
+  // if the returned font does not provide a glyph for the character.
   virtual const scoped_refptr<Font>& GetCharacterFont(
       int32 utf32_character, GlyphIndex* glyph_index) = 0;
 
diff --git a/src/cobalt/render_tree/image.h b/src/cobalt/render_tree/image.h
index 55a1bc8..8faa040 100644
--- a/src/cobalt/render_tree/image.h
+++ b/src/cobalt/render_tree/image.h
@@ -32,6 +32,7 @@
   kPixelFormatY8,
   kPixelFormatU8,
   kPixelFormatV8,
+  kPixelFormatUV8,
   kPixelFormatInvalid,
 };
 
@@ -47,6 +48,8 @@
       return 1;
     case kPixelFormatV8:
       return 1;
+    case kPixelFormatUV8:
+      return 2;
     case kPixelFormatInvalid:
     default:
       DLOG(FATAL) << "Unexpected pixel format.";
@@ -115,6 +118,9 @@
   // A YUV image where each channel, Y, U and V, is stored as a separate
   // single-channel image plane.
   kMultiPlaneImageFormatYUV3PlaneBT709,
+  // A YUV image where the Y channel is stored as a single-channel image plane
+  // and the U and V channels are interleaved in a second image plane.
+  kMultiPlaneImageFormatYUV2PlaneBT709,
 };
 
 // Like the ImageDataDescriptor object, a MultiPlaneImageDataDescriptor
diff --git a/src/cobalt/render_tree/render_tree.gyp b/src/cobalt/render_tree/render_tree.gyp
index 9f53105..5af25ff 100644
--- a/src/cobalt/render_tree/render_tree.gyp
+++ b/src/cobalt/render_tree/render_tree.gyp
@@ -110,7 +110,7 @@
       'variables': {
         'executable_name': 'render_tree_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/renderer/animations_test.cc b/src/cobalt/renderer/animations_test.cc
index 9cd167c..8c488a5 100644
--- a/src/cobalt/renderer/animations_test.cc
+++ b/src/cobalt/renderer/animations_test.cc
@@ -38,18 +38,59 @@
 namespace renderer {
 
 namespace {
+scoped_refptr<Image> CreateDummyImage(ResourceProvider* resource_provider) {
+  // Initialize the image data and store a predictable, testable pattern
+  // of image data into it.
+  math::Size image_size(16, 16);
+
+  int rgba_mapping[4] = {0, 1, 2, 3};
+  render_tree::PixelFormat pixel_format = render_tree::kPixelFormatInvalid;
+  if (resource_provider->PixelFormatSupported(render_tree::kPixelFormatRGBA8)) {
+    pixel_format = render_tree::kPixelFormatRGBA8;
+  } else if (resource_provider->PixelFormatSupported(
+                 render_tree::kPixelFormatBGRA8)) {
+    pixel_format = render_tree::kPixelFormatBGRA8;
+    rgba_mapping[0] = 2;
+    rgba_mapping[2] = 0;
+  } else {
+    NOTREACHED() << "Unsupported pixel format.";
+  }
+
+  scoped_ptr<render_tree::ImageData> image_data =
+      resource_provider->AllocateImageData(
+          image_size, pixel_format, render_tree::kAlphaFormatPremultiplied);
+  for (int i = 0; i < image_size.width() * image_size.height(); ++i) {
+    image_data->GetMemory()[i * 4 + rgba_mapping[0]] = 1;
+    image_data->GetMemory()[i * 4 + rgba_mapping[1]] = 2;
+    image_data->GetMemory()[i * 4 + rgba_mapping[2]] = 3;
+    image_data->GetMemory()[i * 4 + rgba_mapping[3]] = 255;
+  }
+
+  // Create and return the new image.
+  return resource_provider->CreateImage(image_data.Pass());
+}
+
 void AnimateImageNode(base::WaitableEvent* animate_has_started,
                       base::WaitableEvent* image_ready,
-                      scoped_refptr<Image>* image,
+                      scoped_refptr<Image>* image, bool* first_animate,
                       ImageNode::Builder* image_node, base::TimeDelta time) {
   UNREFERENCED_PARAMETER(time);
 
+  if (!*first_animate) {
+    // We only do the test the first time this animation runs, ignore the
+    // subsequent animate calls.
+    return;
+  }
+  *first_animate = false;
+
   // Time to animate the image!  First signal that we are in the animation
   // callback which will prompt the CreateImageThread to create the image.
   animate_has_started->Signal();
   // Wait for the CreateImageThread to finish creating the image.
   image_ready->Wait();
 
+  DCHECK(*image);
+
   // Animate the image node by setting its image to the newly created image.
   image_node->source = *image;
 
@@ -75,35 +116,9 @@
     // animation callback.
     animate_has_started_->Wait();
 
-    // Initialize the image data and store a predictable, testable pattern
-    // of image data into it.
-    math::Size image_size(16, 16);
+    *image_ = CreateDummyImage(resource_provider_);
 
-    int rgba_mapping[4] = {0, 1, 2, 3};
-    render_tree::PixelFormat pixel_format = render_tree::kPixelFormatInvalid;
-    if (resource_provider_->PixelFormatSupported(
-            render_tree::kPixelFormatRGBA8)) {
-      pixel_format = render_tree::kPixelFormatRGBA8;
-    } else if (resource_provider_->PixelFormatSupported(
-                   render_tree::kPixelFormatBGRA8)) {
-      pixel_format = render_tree::kPixelFormatBGRA8;
-      rgba_mapping[0] = 2;
-      rgba_mapping[2] = 0;
-    } else {
-      NOTREACHED() << "Unsupported pixel format.";
-    }
-
-    scoped_ptr<render_tree::ImageData> image_data =
-        resource_provider_->AllocateImageData(
-            image_size, pixel_format, render_tree::kAlphaFormatPremultiplied);
-    for (int i = 0; i < image_size.width() * image_size.height(); ++i) {
-      image_data->GetMemory()[i * 4 + rgba_mapping[0]] = 1;
-      image_data->GetMemory()[i * 4 + rgba_mapping[1]] = 2;
-      image_data->GetMemory()[i * 4 + rgba_mapping[2]] = 3;
-      image_data->GetMemory()[i * 4 + rgba_mapping[3]] = 255;
-    }
-    // Create the new image.
-    *image_ = resource_provider_->CreateImage(image_data.Pass());
+    DCHECK(*image_);
 
     // Signal to the animation callback that it can now reference the newly
     // created image.
@@ -139,7 +154,8 @@
   scoped_refptr<backend::RenderTarget> dummy_output_surface =
       graphics_context->CreateOffscreenRenderTarget(kDummySurfaceDimensions);
 
-  {
+  const int kNumTestTrials = 5;
+  for (int i = 0; i < kNumTestTrials; ++i) {
     // Setup some synchronization objects so we can ensure the image is created
     // while the animation callback is being executed, and also that the image
     // is referenced only after it is created.  It is important that these
@@ -153,19 +169,21 @@
     RendererModule::Options render_module_options;
     Pipeline pipeline(
         base::Bind(render_module_options.create_rasterizer_function,
-                   graphics_context.get()),
+                   graphics_context.get(), render_module_options),
         dummy_output_surface, NULL);
 
     // Our test render tree will consist of only a single ImageNode.
-    scoped_refptr<ImageNode> test_node =
-        new ImageNode(scoped_refptr<Image>(), math::RectF(1.0f, 1.0f));
+    scoped_refptr<ImageNode> test_node = new ImageNode(
+        scoped_refptr<Image>(CreateDummyImage(pipeline.GetResourceProvider())),
+        math::RectF(1.0f, 1.0f));
 
     // Animate the ImageNode and pass in our callback function to be executed
     // upon render_tree animation.
     NodeAnimationsMap::Builder animations;
+    bool first_animate = true;
     animations.Add(test_node,
                    base::Bind(&AnimateImageNode, &animate_has_started,
-                              &image_ready, &image));
+                              &image_ready, &image, &first_animate));
 
     // Setup a separate thread to be responsible for creating the image, so that
     // we can guarantee that this operation will occur on a separate thread.
diff --git a/src/cobalt/renderer/backend/egl/utils.cc b/src/cobalt/renderer/backend/egl/utils.cc
index b8ee608..c72f73e 100644
--- a/src/cobalt/renderer/backend/egl/utils.cc
+++ b/src/cobalt/renderer/backend/egl/utils.cc
@@ -54,6 +54,8 @@
     case GL_RGBA:
     case GL_BGRA_EXT:
       return 4;
+    case GL_LUMINANCE_ALPHA:
+      return 2;
     case GL_ALPHA:
       return 1;
     default:
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
new file mode 100644
index 0000000..6fcae22
--- /dev/null
+++ b/src/cobalt/renderer/glimp_shaders/glsl/fragment_skia_nv12.glsl
@@ -0,0 +1,18 @@
+#version 100
+precision mediump float;
+uniform sampler2D uSampler0_Stage0;
+uniform sampler2D uSampler1_Stage0;
+uniform mat4 uYUVMatrix_Stage0;
+varying vec2 vMatrixCoord_Stage0;
+
+void main() {
+  vec4 output_Stage0;
+  {
+    // Stage 0: YUV to RGB
+    output_Stage0 = vec4(
+        texture2D(uSampler0_Stage0, vMatrixCoord_Stage0).aaaa.r,
+        texture2D(uSampler1_Stage0, vMatrixCoord_Stage0).ba,
+        1.0) * uYUVMatrix_Stage0;
+  }
+  gl_FragColor = output_Stage0;
+}
diff --git a/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi b/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi
index 843878c..b0e8820 100644
--- a/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi
+++ b/src/cobalt/renderer/glimp_shaders/glsl/shaders.gypi
@@ -45,6 +45,7 @@
       'fragment_skia_linear_gradient_many_colors.glsl',
       'fragment_skia_linear_gradient_three_colors.glsl',
       'fragment_skia_linear_gradient_two_colors.glsl',
+      'fragment_skia_nv12.glsl',
       'fragment_skia_radial_gradient_many_colors.glsl',
       'fragment_skia_radial_gradient_three_colors.glsl',
       'fragment_skia_radial_gradient_two_colors.glsl',
diff --git a/src/cobalt/renderer/rasterizer/benchmark.cc b/src/cobalt/renderer/rasterizer/benchmark.cc
index ffc3fe8..aefb362 100644
--- a/src/cobalt/renderer/rasterizer/benchmark.cc
+++ b/src/cobalt/renderer/rasterizer/benchmark.cc
@@ -50,7 +50,8 @@
 scoped_ptr<Rasterizer> CreateDefaultRasterizer(
     GraphicsContext* graphics_context) {
   RendererModule::Options render_module_options;
-  return render_module_options.create_rasterizer_function.Run(graphics_context);
+  return render_module_options.create_rasterizer_function.Run(
+      graphics_context, render_module_options);
 }
 
 // Allow test writers to choose whether the rasterizer results should be drawn
diff --git a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
index e2102eb..2f73a29 100644
--- a/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/hardware_rasterizer.cc
@@ -52,7 +52,7 @@
 
   backend::GraphicsContextBlitter* context_;
 
-  skia::SkiaSoftwareRasterizer software_rasterizer_;
+  skia::SoftwareRasterizer software_rasterizer_;
   scoped_ptr<render_tree::ResourceProvider> resource_provider_;
 
   int64 submit_count_;
diff --git a/src/cobalt/renderer/rasterizer/blitter/image.h b/src/cobalt/renderer/rasterizer/blitter/image.h
index 4a2b1ec..7275225 100644
--- a/src/cobalt/renderer/rasterizer/blitter/image.h
+++ b/src/cobalt/renderer/rasterizer/blitter/image.h
@@ -64,11 +64,11 @@
 
 // render_tree::Image objects are implemented in the Blitter API via
 // SbBlitterSurface objects, which are conceptually an exact match for Image.
-// We derive from skia::SkiaSinglePlaneImage here because it is possible for
+// We derive from skia::SinglePlaneImage here because it is possible for
 // render tree nodes referencing blitter:Images to be passed into a Skia
 // software renderer.  Thus, SinglePlaneImage is implemented such
 // that Skia render tree node visitors can also render it.
-class SinglePlaneImage : public skia::SkiaSinglePlaneImage {
+class SinglePlaneImage : public skia::SinglePlaneImage {
  public:
   explicit SinglePlaneImage(scoped_ptr<ImageData> image_data);
 
@@ -76,7 +76,7 @@
 
   SbBlitterSurface surface() const { return surface_; }
 
-  // Overrides from skia::SkiaSinglePlaneImage.
+  // Overrides from skia::SinglePlaneImage.
   void EnsureInitialized() OVERRIDE;
 
   // When GetBitmap() is called on a blitter::SinglePlaneImage for the first
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
index 1888a53..9af227b 100644
--- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.cc
@@ -53,7 +53,7 @@
 RenderTreeNodeVisitor::RenderTreeNodeVisitor(
     SbBlitterDevice device, SbBlitterContext context,
     const RenderState& render_state,
-    skia::SkiaSoftwareRasterizer* software_rasterizer,
+    skia::SoftwareRasterizer* software_rasterizer,
     SurfaceCacheDelegate* surface_cache_delegate,
     common::SurfaceCache* surface_cache)
     : software_rasterizer_(software_rasterizer),
@@ -167,14 +167,14 @@
 }
 
 void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
-  // All Blitter API images derive from SkiaImage (so that they can be
+  // All Blitter API images derive from skia::Image (so that they can be
   // compatible with the Skia software renderer), so we start here by casting
-  // to SkiaImage.
-  skia::SkiaImage* skia_image = base::polymorphic_downcast<skia::SkiaImage*>(
-      image_node->data().source.get());
+  // to skia::Image.
+  skia::Image* skia_image =
+      base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());
   const Size& image_size = skia_image->GetSize();
 
-  if (skia_image->GetTypeId() == base::GetTypeId<skia::SkiaMultiPlaneImage>()) {
+  if (skia_image->GetTypeId() == base::GetTypeId<skia::MultiPlaneImage>()) {
     // Let software Skia deal with multiplane (e.g. YUV) image rendering.
     RenderWithSoftwareRenderer(image_node);
     return;
diff --git a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
index 16d774b..3370321 100644
--- a/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
+++ b/src/cobalt/renderer/rasterizer/blitter/render_tree_node_visitor.h
@@ -54,7 +54,7 @@
  public:
   RenderTreeNodeVisitor(SbBlitterDevice device, SbBlitterContext context,
                         const RenderState& render_state,
-                        skia::SkiaSoftwareRasterizer* software_rasterizer,
+                        skia::SoftwareRasterizer* software_rasterizer,
                         SurfaceCacheDelegate* surface_cache_delegate,
                         common::SurfaceCache* surface_cache);
 
@@ -89,7 +89,7 @@
 
   // We maintain an instance of a software skia rasterizer which is used to
   // render anything that we cannot render via the Blitter API directly.
-  skia::SkiaSoftwareRasterizer* software_rasterizer_;
+  skia::SoftwareRasterizer* software_rasterizer_;
 
   SbBlitterDevice device_;
   SbBlitterContext context_;
diff --git a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
index 874160f..4743332 100644
--- a/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/blitter/software_rasterizer.h
@@ -50,7 +50,7 @@
 
  private:
   backend::GraphicsContextBlitter* context_;
-  skia::SkiaSoftwareRasterizer skia_rasterizer_;
+  skia::SoftwareRasterizer skia_rasterizer_;
 };
 
 }  // namespace blitter
diff --git a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
index 9330b45..662353c 100644
--- a/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/egl/software_rasterizer.h
@@ -50,7 +50,7 @@
 
  private:
   backend::GraphicsContextEGL* context_;
-  skia::SkiaSoftwareRasterizer skia_rasterizer_;
+  skia::SoftwareRasterizer skia_rasterizer_;
 };
 
 }  // namespace egl
diff --git a/src/cobalt/renderer/rasterizer/pixel_test.cc b/src/cobalt/renderer/rasterizer/pixel_test.cc
index d87d57a..5fde5c2 100644
--- a/src/cobalt/renderer/rasterizer/pixel_test.cc
+++ b/src/cobalt/renderer/rasterizer/pixel_test.cc
@@ -43,6 +43,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 
 #define BILINEAR_FILTERING_SUPPORTED 1
+#define NV12_TEXTURE_SUPPORTED 1
 
 #if defined(STARBOARD)
 #if !SB_HAS(BILINEAR_FILTERING_SUPPORT)
@@ -51,6 +52,13 @@
 #endif
 #endif
 
+#if defined(STARBOARD)
+#if !SB_HAS(NV12_TEXTURE_SUPPORT)
+#undef NV12_TEXTURE_SUPPORTED
+#define NV12_TEXTURE_SUPPORTED 0
+#endif
+#endif
+
 using cobalt::math::Matrix3F;
 using cobalt::math::PointF;
 using cobalt::math::RectF;
@@ -374,6 +382,7 @@
     case render_tree::kPixelFormatY8:
     case render_tree::kPixelFormatU8:
     case render_tree::kPixelFormatV8:
+    case render_tree::kPixelFormatUV8:
     case render_tree::kPixelFormatInvalid: {
       NOTREACHED() << "Invalid pixel format.";
     }
@@ -895,6 +904,74 @@
   return resource_provider->CreateMultiPlaneImageFromRawMemory(
       image_memory.Pass(), image_data_descriptor);
 }
+
+// The software rasterizer does not support NV12 images.
+#if NV12_TEXTURE_SUPPORTED
+
+// Creates a two plane YUV image where the Y channel is stored as a
+// single-channel image plane and the U and V channels are interleaved in a
+// second image plane. The NV12 format dictates that the UV plane has the same
+// number of columns and half the rows of the Y plane.
+scoped_refptr<Image> MakeNV12Image(ResourceProvider* resource_provider,
+                                   const Size& image_size) {
+  // The alpha format doesn't really matter here, but we still need to pick one
+  // that the resource provider indicates it supports.
+  render_tree::AlphaFormat alpha_format =
+      render_tree::kAlphaFormatUnpremultiplied;
+  if (!resource_provider->AlphaFormatSupported(alpha_format)) {
+    alpha_format = render_tree::kAlphaFormatPremultiplied;
+  }
+  CHECK(resource_provider->AlphaFormatSupported(alpha_format));
+
+  static const int kMaxBytesUsed =
+      image_size.width() * image_size.height() * 3 / 2;
+
+  scoped_ptr<RawImageMemory> image_memory =
+      resource_provider->AllocateRawImageMemory(kMaxBytesUsed, 256);
+
+  // Setup information about the Y plane.
+  ImageDataDescriptor y_plane_descriptor(image_size,
+                                         render_tree::kPixelFormatY8,
+                                         alpha_format, image_size.width());
+  intptr_t y_plane_memory_offset = 0;
+  uint8_t* y_plane_memory = image_memory->GetMemory() + y_plane_memory_offset;
+  float y_plane_inverse_height = 1.0f / y_plane_descriptor.size.height();
+  for (int r = 0; r < y_plane_descriptor.size.height(); ++r) {
+    for (int c = 0; c < y_plane_descriptor.size.width(); ++c) {
+      y_plane_memory[c] =
+          static_cast<uint8_t>(255.0f * r * y_plane_inverse_height);
+    }
+    y_plane_memory += y_plane_descriptor.pitch_in_bytes;
+  }
+
+  // Setup information about the UV plane.
+  ImageDataDescriptor uv_plane_descriptor(
+      Size(image_size.width() / 2, image_size.height() / 2),
+      render_tree::kPixelFormatUV8, alpha_format, image_size.width());
+  intptr_t uv_plane_memory_offset =
+      y_plane_memory_offset +
+      y_plane_descriptor.pitch_in_bytes * y_plane_descriptor.size.height();
+  uint8_t* uv_plane_memory = image_memory->GetMemory() + uv_plane_memory_offset;
+  float uv_plane_inverse_width = 1.0f / uv_plane_descriptor.size.width();
+  for (int r = 0; r < uv_plane_descriptor.size.height(); ++r) {
+    for (int c = 0; c < uv_plane_descriptor.size.width(); ++c) {
+      uv_plane_memory[2 * c] =
+          static_cast<uint8_t>(255.0f * c * uv_plane_inverse_width);
+      uv_plane_memory[2 * c + 1] =
+          255 - static_cast<uint8_t>(255.0f * c * uv_plane_inverse_width);
+    }
+    uv_plane_memory += uv_plane_descriptor.pitch_in_bytes;
+  }
+
+  MultiPlaneImageDataDescriptor image_data_descriptor(
+      render_tree::kMultiPlaneImageFormatYUV2PlaneBT709);
+  image_data_descriptor.AddPlane(y_plane_memory_offset, y_plane_descriptor);
+  image_data_descriptor.AddPlane(uv_plane_memory_offset, uv_plane_descriptor);
+
+  return resource_provider->CreateMultiPlaneImageFromRawMemory(
+      image_memory.Pass(), image_data_descriptor);
+}
+#endif  // #if NV12_TEXTURE_SUPPORTED
 }  // namespace
 
 TEST_F(PixelTest, ThreePlaneYUVImageSupport) {
@@ -924,6 +1001,37 @@
                           -half_output_size.height())));
 }
 
+// The software rasterizer does not support NV12 images.
+#if NV12_TEXTURE_SUPPORTED
+
+TEST_F(PixelTest, TwoPlaneYUVImageSupport) {
+  // Tests that an ImageNode hooked up to a 3-plane YUV image works fine.
+  scoped_refptr<Image> image =
+      MakeNV12Image(GetResourceProvider(), output_surface_size());
+
+  TestTree(new ImageNode(image));
+}
+
+TEST_F(PixelTest, TwoPlaneYUVImageWithDestSizeDifferentFromImage) {
+  // Tests that an ImageNode hooked up to a 3-plane YUV image works fine.
+  scoped_refptr<Image> image =
+      MakeNV12Image(GetResourceProvider(), output_surface_size());
+
+  TestTree(new ImageNode(image, RectF(100.0f, 100.0f)));
+}
+
+TEST_F(PixelTest, TwoPlaneYUVImageWithTransform) {
+  SizeF half_output_size = ScaleSize(output_surface_size(), 0.5f, 0.5f);
+  TestTree(new MatrixTransformNode(
+      new ImageNode(
+          MakeNV12Image(GetResourceProvider(), output_surface_size())),
+      TranslateMatrix(half_output_size.width(), half_output_size.height()) *
+          ScaleMatrix(0.5f) * RotateMatrix(static_cast<float>(M_PI) / 4) *
+          TranslateMatrix(-half_output_size.width(),
+                          -half_output_size.height())));
+}
+#endif  // #if NV12_TEXTURE_SUPPORTED
+
 TEST_F(PixelTest, ImageNodeLocalTransformRotationAndScale) {
   scoped_refptr<Image> image =
       CreateColoredCheckersImage(GetResourceProvider(), output_surface_size());
@@ -1386,13 +1494,25 @@
 
 #endif  // BILINEAR_FILTERING_SUPPORTED
 
-TEST_F(PixelTest, YUVImagesAreLinearlyInterpolated) {
-  // Tests that YUV images are bilinearly interpolated.
+TEST_F(PixelTest, YUV3PlaneImagesAreLinearlyInterpolated) {
+  // Tests that three plane YUV images are bilinearly interpolated.
   scoped_refptr<Image> image = MakeI420Image(GetResourceProvider(), Size(8, 8));
 
   TestTree(new ImageNode(image, RectF(output_surface_size())));
 }
 
+// The software rasterizer does not support NV12 images.
+#if NV12_TEXTURE_SUPPORTED
+
+TEST_F(PixelTest, YUV2PlaneImagesAreLinearlyInterpolated) {
+  // Tests that two plane YUV images are bilinearly interpolated.
+  scoped_refptr<Image> image = MakeNV12Image(GetResourceProvider(), Size(8, 8));
+
+  TestTree(new ImageNode(image, RectF(output_surface_size())));
+}
+
+#endif  // #if NV12_TEXTURE_SUPPORTED
+
 TEST_F(PixelTest, VeryLargeOpacityFilterDoesNotOccupyVeryMuchMemory) {
   // This test ensures that an opacity filter being applied to an extremely
   // large surface works just fine.  This test is itneresting because opacity
diff --git a/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc b/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc
index 39c12c7..1ca29c1 100644
--- a/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc
+++ b/src/cobalt/renderer/rasterizer/skia/cobalt_skia_type_conversions.cc
@@ -34,6 +34,8 @@
       return kAlpha_8_SkColorType;
     case render_tree::kPixelFormatV8:
       return kAlpha_8_SkColorType;
+    case render_tree::kPixelFormatUV8:
+      return kRGBA_8888_SkColorType;
     default:
       DLOG(FATAL) << "Unknown render tree pixel format!";
       return kUnknown_SkColorType;
diff --git a/src/cobalt/renderer/rasterizer/skia/font.cc b/src/cobalt/renderer/rasterizer/skia/font.cc
index 3e54684..06bbb20 100644
--- a/src/cobalt/renderer/rasterizer/skia/font.cc
+++ b/src/cobalt/renderer/rasterizer/skia/font.cc
@@ -49,20 +49,18 @@
 
 }  // namespace
 
-SkiaFont::SkiaFont(SkiaTypeface* typeface, SkScalar size)
+Font::Font(SkiaTypeface* typeface, SkScalar size)
     : typeface_(typeface), size_(size) {
   glyph_bounds_thread_checker_.DetachFromThread();
 }
 
-SkTypeface* SkiaFont::GetSkTypeface() const {
-  return typeface_->GetSkTypeface();
-}
+SkTypeface* Font::GetSkTypeface() const { return typeface_->GetSkTypeface(); }
 
-render_tree::TypefaceId SkiaFont::GetTypefaceId() const {
+render_tree::TypefaceId Font::GetTypefaceId() const {
   return typeface_->GetId();
 }
 
-render_tree::FontMetrics SkiaFont::GetFontMetrics() const {
+render_tree::FontMetrics Font::GetFontMetrics() const {
   SkPaint paint = GetSkPaint();
 
   SkPaint::FontMetrics font_metrics;
@@ -85,11 +83,11 @@
                                   font_metrics.fLeading, x_height);
 }
 
-render_tree::GlyphIndex SkiaFont::GetGlyphForCharacter(int32 utf32_character) {
+render_tree::GlyphIndex Font::GetGlyphForCharacter(int32 utf32_character) {
   return typeface_->GetGlyphForCharacter(utf32_character);
 }
 
-const math::RectF& SkiaFont::GetGlyphBounds(render_tree::GlyphIndex glyph) {
+const math::RectF& Font::GetGlyphBounds(render_tree::GlyphIndex glyph) {
   DCHECK(glyph_bounds_thread_checker_.CalledOnValidThread());
   // Check to see if the glyph falls within the the first 256 glyphs. These
   // characters are part of the primary page and are stored within an array as
@@ -132,11 +130,11 @@
   }
 }
 
-float SkiaFont::GetGlyphWidth(render_tree::GlyphIndex glyph) {
+float Font::GetGlyphWidth(render_tree::GlyphIndex glyph) {
   return GetGlyphBounds(glyph).width();
 }
 
-SkPaint SkiaFont::GetSkPaint() const {
+SkPaint Font::GetSkPaint() const {
   SkPaint paint(GetDefaultSkPaint());
   SkAutoTUnref<SkTypeface> typeface(typeface_->GetSkTypeface());
   paint.setTypeface(typeface);
@@ -144,7 +142,7 @@
   return paint;
 }
 
-const SkPaint& SkiaFont::GetDefaultSkPaint() {
+const SkPaint& Font::GetDefaultSkPaint() {
   return non_trivial_static_fields.Get().default_paint;
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/font.h b/src/cobalt/renderer/rasterizer/skia/font.h
index d6e181c..d0e9ea5 100644
--- a/src/cobalt/renderer/rasterizer/skia/font.h
+++ b/src/cobalt/renderer/rasterizer/skia/font.h
@@ -39,9 +39,9 @@
 // NOTE: Glyph queries are not thread-safe and should only occur from a single
 // thread. However, the font can be created on a different thread than the
 // thread making the glyph queries.
-class SkiaFont : public render_tree::Font {
+class Font : public render_tree::Font {
  public:
-  SkiaFont(SkiaTypeface* typeface, SkScalar size);
+  Font(SkiaTypeface* typeface, SkScalar size);
 
   SkTypeface* GetSkTypeface() const;
 
diff --git a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc
index 70bbd7a..02e1ed8 100644
--- a/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc
+++ b/src/cobalt/renderer/rasterizer/skia/gl_format_conversions.cc
@@ -36,6 +36,8 @@
       return GL_ALPHA;
     case render_tree::kPixelFormatV8:
       return GL_ALPHA;
+    case render_tree::kPixelFormatUV8:
+      return GL_LUMINANCE_ALPHA;
     default: { NOTREACHED() << "Unknown format."; }
   }
   return GL_RGBA;
@@ -49,6 +51,8 @@
       return kBGRA_8888_GrPixelConfig;
     case GL_ALPHA:
       return kAlpha_8_GrPixelConfig;
+    case GL_LUMINANCE_ALPHA:
+      return kRGBA_8888_GrPixelConfig;
     default: { NOTREACHED() << "Unsupported GL format."; }
   }
   return kRGBA_8888_GrPixelConfig;
diff --git a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc
index acbd7a5..a9fc8a1 100644
--- a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.cc
@@ -21,11 +21,10 @@
 namespace rasterizer {
 namespace skia {
 
-SkiaGlyphBuffer::SkiaGlyphBuffer(const math::RectF& bounds,
-                                 SkTextBlobBuilder* builder)
+GlyphBuffer::GlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder)
     : render_tree::GlyphBuffer(bounds), text_blob_(builder->build()) {}
 
-const SkTextBlob* SkiaGlyphBuffer::GetTextBlob() const {
+const SkTextBlob* GlyphBuffer::GetTextBlob() const {
   return SkSafeRef(text_blob_.get());
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h
index b1a39a2..ca1f86d 100644
--- a/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h
+++ b/src/cobalt/renderer/rasterizer/skia/glyph_buffer.h
@@ -29,9 +29,9 @@
 // Describes a render_tree::GlyphBuffer using Skia. This object contain all of
 // the information needed by Skia to render glyphs and is both immutable and
 // thread-safe.
-class SkiaGlyphBuffer : public render_tree::GlyphBuffer {
+class GlyphBuffer : public render_tree::GlyphBuffer {
  public:
-  SkiaGlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder);
+  GlyphBuffer(const math::RectF& bounds, SkTextBlobBuilder* builder);
 
   const SkTextBlob* GetTextBlob() const;
 
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
index f45500a..f8096b0 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.cc
@@ -46,7 +46,7 @@
   return gr_context->wrapBackendTexture(desc);
 }
 
-SkiaHardwareImageData::SkiaHardwareImageData(
+HardwareImageData::HardwareImageData(
     scoped_ptr<backend::TextureDataEGL> texture_data,
     render_tree::PixelFormat pixel_format,
     render_tree::AlphaFormat alpha_format)
@@ -54,33 +54,31 @@
       descriptor_(texture_data_->GetSize(), pixel_format, alpha_format,
                   texture_data_->GetPitchInBytes()) {}
 
-const render_tree::ImageDataDescriptor& SkiaHardwareImageData::GetDescriptor()
+const render_tree::ImageDataDescriptor& HardwareImageData::GetDescriptor()
     const {
   return descriptor_;
 }
 
-uint8_t* SkiaHardwareImageData::GetMemory() {
-  return texture_data_->GetMemory();
-}
+uint8_t* HardwareImageData::GetMemory() { return texture_data_->GetMemory(); }
 
-scoped_ptr<backend::TextureDataEGL> SkiaHardwareImageData::PassTextureData() {
+scoped_ptr<backend::TextureDataEGL> HardwareImageData::PassTextureData() {
   return texture_data_.Pass();
 }
 
-SkiaHardwareRawImageMemory::SkiaHardwareRawImageMemory(
+HardwareRawImageMemory::HardwareRawImageMemory(
     scoped_ptr<backend::RawTextureMemoryEGL> raw_texture_memory)
     : raw_texture_memory_(raw_texture_memory.Pass()) {}
 
-size_t SkiaHardwareRawImageMemory::GetSizeInBytes() const {
+size_t HardwareRawImageMemory::GetSizeInBytes() const {
   return raw_texture_memory_->GetSizeInBytes();
 }
 
-uint8_t* SkiaHardwareRawImageMemory::GetMemory() {
+uint8_t* HardwareRawImageMemory::GetMemory() {
   return raw_texture_memory_->GetMemory();
 }
 
 scoped_ptr<backend::RawTextureMemoryEGL>
-SkiaHardwareRawImageMemory::PassRawTextureMemory() {
+HardwareRawImageMemory::PassRawTextureMemory() {
   return raw_texture_memory_.Pass();
 }
 
@@ -88,26 +86,27 @@
 // GetBitmap(), overridden from SkiaImage, will return a reference to a SkBitmap
 // object that refers to the image's GrTexture.  This object should only be
 // constructed, destructed and used from the same rasterizer thread.
-class SkiaHardwareFrontendImage::SkiaHardwareBackendImage {
+class HardwareFrontendImage::HardwareBackendImage {
  public:
-  SkiaHardwareBackendImage(scoped_ptr<SkiaHardwareImageData> image_data,
-                           backend::GraphicsContextEGL* cobalt_context,
-                           GrContext* gr_context) {
+  HardwareBackendImage(scoped_ptr<HardwareImageData> image_data,
+                       backend::GraphicsContextEGL* cobalt_context,
+                       GrContext* gr_context) {
     TRACE_EVENT0("cobalt::renderer",
-                 "SkiaHardwareBackendImage::SkiaHardwareBackendImage()");
+                 "HardwareBackendImage::HardwareBackendImage()");
     scoped_ptr<backend::TextureEGL> texture =
         cobalt_context->CreateTexture(image_data->PassTextureData());
 
     CommonInitialize(texture.Pass(), gr_context);
   }
 
-  SkiaHardwareBackendImage(
-      const scoped_refptr<backend::ConstRawTextureMemoryEGL>&
-          raw_texture_memory,
-      intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
-      backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) {
+  HardwareBackendImage(const scoped_refptr<backend::ConstRawTextureMemoryEGL>&
+                           raw_texture_memory,
+                       intptr_t offset,
+                       const render_tree::ImageDataDescriptor& descriptor,
+                       backend::GraphicsContextEGL* cobalt_context,
+                       GrContext* gr_context) {
     TRACE_EVENT0("cobalt::renderer",
-                 "SkiaHardwareBackendImage::SkiaHardwareBackendImage()");
+                 "HardwareBackendImage::HardwareBackendImage()");
     scoped_ptr<backend::TextureEGL> texture =
         cobalt_context->CreateTextureFromRawMemory(
             raw_texture_memory, offset, descriptor.size,
@@ -117,9 +116,9 @@
     CommonInitialize(texture.Pass(), gr_context);
   }
 
-  ~SkiaHardwareBackendImage() {
+  ~HardwareBackendImage() {
     TRACE_EVENT0("cobalt::renderer",
-                 "SkiaHardwareBackendImage::~SkiaHardwareBackendImage()");
+                 "HardwareBackendImage::~HardwareBackendImage()");
     // This object should always be destroyed from the thread that it was
     // constructed on.
     DCHECK(thread_checker_.CalledOnValidThread());
@@ -131,11 +130,12 @@
                         GrContext* gr_context) {
     DCHECK(thread_checker_.CalledOnValidThread());
     TRACE_EVENT0("cobalt::renderer",
-                 "SkiaHardwareBackendImage::CommonInitialize()");
+                 "HardwareBackendImage::CommonInitialize()");
 
     texture_ = texture.Pass();
     gr_texture_.reset(
         WrapCobaltTextureWithSkiaTexture(gr_context, texture_.get()));
+    DCHECK(gr_texture_);
 
     // Prepare a member SkBitmap that refers to the newly created GrTexture and
     // will be the object that Skia draw calls will reference when referring
@@ -160,22 +160,22 @@
   SkBitmap bitmap_;
 };
 
-SkiaHardwareFrontendImage::SkiaHardwareFrontendImage(
-    scoped_ptr<SkiaHardwareImageData> image_data,
+HardwareFrontendImage::HardwareFrontendImage(
+    scoped_ptr<HardwareImageData> image_data,
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
     MessageLoop* rasterizer_message_loop)
     : size_(image_data->GetDescriptor().size),
       rasterizer_message_loop_(rasterizer_message_loop) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareFrontendImage::SkiaHardwareFrontendImage()");
+               "HardwareFrontendImage::HardwareFrontendImage()");
 
-  initialize_backend_image_ = base::Bind(
-      &SkiaHardwareFrontendImage::InitializeBackendImageFromImageData,
-      base::Unretained(this), base::Passed(&image_data), cobalt_context,
-      gr_context);
+  initialize_backend_image_ =
+      base::Bind(&HardwareFrontendImage::InitializeBackendImageFromImageData,
+                 base::Unretained(this), base::Passed(&image_data),
+                 cobalt_context, gr_context);
 }
 
-SkiaHardwareFrontendImage::SkiaHardwareFrontendImage(
+HardwareFrontendImage::HardwareFrontendImage(
     const scoped_refptr<backend::ConstRawTextureMemoryEGL>& raw_texture_memory,
     intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
@@ -183,16 +183,16 @@
     : size_(descriptor.size),
       rasterizer_message_loop_(rasterizer_message_loop) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareFrontendImage::SkiaHardwareFrontendImage()");
-  initialize_backend_image_ = base::Bind(
-      &SkiaHardwareFrontendImage::InitializeBackendImageFromRawImageData,
-      base::Unretained(this), raw_texture_memory, offset, descriptor,
-      cobalt_context, gr_context);
+               "HardwareFrontendImage::HardwareFrontendImage()");
+  initialize_backend_image_ =
+      base::Bind(&HardwareFrontendImage::InitializeBackendImageFromRawImageData,
+                 base::Unretained(this), raw_texture_memory, offset, descriptor,
+                 cobalt_context, gr_context);
 }
 
-SkiaHardwareFrontendImage::~SkiaHardwareFrontendImage() {
+HardwareFrontendImage::~HardwareFrontendImage() {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareFrontendImage::~SkiaHardwareFrontendImage()");
+               "HardwareFrontendImage::~HardwareFrontendImage()");
   // If we are destroying this image from a non-rasterizer thread, we still must
   // ensure that the |backend_image_| is destroyed from the rasterizer thread,
   // if |backend_image_| was ever constructed in the first place.
@@ -202,7 +202,7 @@
   }  // else let the scoped pointer clean it up immediately.
 }
 
-const SkBitmap& SkiaHardwareFrontendImage::GetBitmap() const {
+const SkBitmap& HardwareFrontendImage::GetBitmap() const {
   DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
   // Forward this call to the backend image.  This method must be called from
   // the rasterizer thread (e.g. during a render tree visitation).  The backend
@@ -210,7 +210,7 @@
   return backend_image_->GetBitmap();
 }
 
-void SkiaHardwareFrontendImage::EnsureInitialized() {
+void HardwareFrontendImage::EnsureInitialized() {
   DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
   if (!initialize_backend_image_.is_null()) {
     initialize_backend_image_.Run();
@@ -218,25 +218,25 @@
   }
 }
 
-void SkiaHardwareFrontendImage::InitializeBackendImageFromImageData(
-    scoped_ptr<SkiaHardwareImageData> image_data,
+void HardwareFrontendImage::InitializeBackendImageFromImageData(
+    scoped_ptr<HardwareImageData> image_data,
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) {
   DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
-  backend_image_.reset(new SkiaHardwareBackendImage(
-      image_data.Pass(), cobalt_context, gr_context));
+  backend_image_.reset(
+      new HardwareBackendImage(image_data.Pass(), cobalt_context, gr_context));
 }
 
-void SkiaHardwareFrontendImage::InitializeBackendImageFromRawImageData(
+void HardwareFrontendImage::InitializeBackendImageFromRawImageData(
     const scoped_refptr<backend::ConstRawTextureMemoryEGL>& raw_texture_memory,
     intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context) {
   DCHECK_EQ(rasterizer_message_loop_, MessageLoop::current());
-  backend_image_.reset(new SkiaHardwareBackendImage(
+  backend_image_.reset(new HardwareBackendImage(
       raw_texture_memory, offset, descriptor, cobalt_context, gr_context));
 }
 
-SkiaHardwareMultiPlaneImage::SkiaHardwareMultiPlaneImage(
-    scoped_ptr<SkiaHardwareRawImageMemory> raw_image_memory,
+HardwareMultiPlaneImage::HardwareMultiPlaneImage(
+    scoped_ptr<HardwareRawImageMemory> raw_image_memory,
     const render_tree::MultiPlaneImageDataDescriptor& descriptor,
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
     MessageLoop* rasterizer_message_loop)
@@ -248,16 +248,16 @@
 
   // Construct a single plane image for each plane of this multi plane image.
   for (int i = 0; i < descriptor.num_planes(); ++i) {
-    planes_[i] = new SkiaHardwareFrontendImage(
+    planes_[i] = new HardwareFrontendImage(
         const_raw_texture_memory, descriptor.GetPlaneOffset(i),
         descriptor.GetPlaneDescriptor(i), cobalt_context, gr_context,
         rasterizer_message_loop);
   }
 }
 
-SkiaHardwareMultiPlaneImage::~SkiaHardwareMultiPlaneImage() {}
+HardwareMultiPlaneImage::~HardwareMultiPlaneImage() {}
 
-void SkiaHardwareMultiPlaneImage::EnsureInitialized() {
+void HardwareMultiPlaneImage::EnsureInitialized() {
   // A multi-plane image is not considered backend-initialized until all its
   // single-plane images are backend-initialized, thus we ensure that all
   // the component images are backend-initialized.
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_image.h b/src/cobalt/renderer/rasterizer/skia/hardware_image.h
index d222471..15c318e 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_image.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_image.h
@@ -40,11 +40,11 @@
     GrContext* gr_context, scoped_ptr<backend::TextureEGL> cobalt_texture);
 
 // Forwards ImageData methods on to TextureData methods.
-class SkiaHardwareImageData : public render_tree::ImageData {
+class HardwareImageData : public render_tree::ImageData {
  public:
-  SkiaHardwareImageData(scoped_ptr<backend::TextureDataEGL> texture_data,
-                        render_tree::PixelFormat pixel_format,
-                        render_tree::AlphaFormat alpha_format);
+  HardwareImageData(scoped_ptr<backend::TextureDataEGL> texture_data,
+                    render_tree::PixelFormat pixel_format,
+                    render_tree::AlphaFormat alpha_format);
 
   const render_tree::ImageDataDescriptor& GetDescriptor() const OVERRIDE;
   uint8_t* GetMemory() OVERRIDE;
@@ -56,9 +56,9 @@
   render_tree::ImageDataDescriptor descriptor_;
 };
 
-class SkiaHardwareRawImageMemory : public render_tree::RawImageMemory {
+class HardwareRawImageMemory : public render_tree::RawImageMemory {
  public:
-  SkiaHardwareRawImageMemory(
+  HardwareRawImageMemory(
       scoped_ptr<backend::RawTextureMemoryEGL> raw_texture_memory);
 
   size_t GetSizeInBytes() const OVERRIDE;
@@ -74,27 +74,28 @@
 // constructed, it also sends a message to the rasterizer's thread to have
 // a corresponding backend image object constructed with the actual image data.
 // The frontend image is what is actually returned from a call to
-// SkiaHardwareResourceProvider::CreateImage(), but the backend object is what
+// HardwareResourceProvider::CreateImage(), but the backend object is what
 // actually contains the texture data.
-class SkiaHardwareFrontendImage : public SkiaSinglePlaneImage {
+class HardwareFrontendImage : public SinglePlaneImage {
  public:
-  SkiaHardwareFrontendImage(scoped_ptr<SkiaHardwareImageData> image_data,
-                            backend::GraphicsContextEGL* cobalt_context,
-                            GrContext* gr_context,
-                            MessageLoop* rasterizer_message_loop);
-  SkiaHardwareFrontendImage(
-      const scoped_refptr<backend::ConstRawTextureMemoryEGL>&
-          raw_texture_memory,
-      intptr_t offset, const render_tree::ImageDataDescriptor& descriptor,
-      backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
-      MessageLoop* rasterizer_message_loop);
+  HardwareFrontendImage(scoped_ptr<HardwareImageData> image_data,
+                        backend::GraphicsContextEGL* cobalt_context,
+                        GrContext* gr_context,
+                        MessageLoop* rasterizer_message_loop);
+  HardwareFrontendImage(const scoped_refptr<backend::ConstRawTextureMemoryEGL>&
+                            raw_texture_memory,
+                        intptr_t offset,
+                        const render_tree::ImageDataDescriptor& descriptor,
+                        backend::GraphicsContextEGL* cobalt_context,
+                        GrContext* gr_context,
+                        MessageLoop* rasterizer_message_loop);
 
   const math::Size& GetSize() const OVERRIDE { return size_; }
 
   // This method must only be called on the rasterizer thread.  This should not
-  // be tricky to enforce since it is declared in SkiaImage, and not Image.
+  // be tricky to enforce since it is declared in skia::Image, and not Image.
   // The outside world deals only with Image objects and typically it is only
-  // the skia render tree visitor that is aware of SkiaImages.  Since the
+  // the skia render tree visitor that is aware of skia::Images.  Since the
   // skia render tree should only be visited on the rasterizer thread, this
   // restraint should always be satisfied naturally.
   const SkBitmap& GetBitmap() const OVERRIDE;
@@ -102,12 +103,12 @@
   void EnsureInitialized() OVERRIDE;
 
  private:
-  ~SkiaHardwareFrontendImage() OVERRIDE;
+  ~HardwareFrontendImage() OVERRIDE;
 
   // The following Initialize functions will construct |backend_image_|, but
   // only if |backend_image_| is ever needed by the rasterizer thread.
   void InitializeBackendImageFromImageData(
-      scoped_ptr<SkiaHardwareImageData> image_data,
+      scoped_ptr<HardwareImageData> image_data,
       backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context);
   void InitializeBackendImageFromRawImageData(
       const scoped_refptr<backend::ConstRawTextureMemoryEGL>&
@@ -121,20 +122,20 @@
 
   // We keep track of a message loop which indicates the loop upon which we
   // can issue graphics commands.  Specifically, this is the message loop
-  // where all SkiaHardwareBackendImage (described below) logic is executed
+  // where all HardwareBackendImage (described below) logic is executed
   // on.
   MessageLoop* rasterizer_message_loop_;
 
-  // The SkiaHardwareBackendImage object is where all our rasterizer thread
+  // The HardwareBackendImage object is where all our rasterizer thread
   // specific objects live, such as the backend Skia graphics reference to
   // the texture object.  These items typically must be created, accessed and
   // destroyed all on the same thread, and so this object's methods should
   // always be executed on the rasterizer thread.  It is constructed when
-  // the SkiaHardwareFrontendImage is constructed, but destroyed when
-  // a message sent by SkiaHardwareFrontendImage's destructor is received by
+  // the HardwareFrontendImage is constructed, but destroyed when
+  // a message sent by HardwareFrontendImage's destructor is received by
   // the rasterizer thread.
-  class SkiaHardwareBackendImage;
-  scoped_ptr<SkiaHardwareBackendImage> backend_image_;
+  class HardwareBackendImage;
+  scoped_ptr<HardwareBackendImage> backend_image_;
 
   // This closure binds the backend image construction parameters so that we
   // can delay construction of it until it is accessed by the rasterizer thread.
@@ -144,10 +145,10 @@
 };
 
 // Multi-plane images are implemented as collections of single plane images.
-class SkiaHardwareMultiPlaneImage : public SkiaMultiPlaneImage {
+class HardwareMultiPlaneImage : public MultiPlaneImage {
  public:
-  SkiaHardwareMultiPlaneImage(
-      scoped_ptr<SkiaHardwareRawImageMemory> raw_image_memory,
+  HardwareMultiPlaneImage(
+      scoped_ptr<HardwareRawImageMemory> raw_image_memory,
       const render_tree::MultiPlaneImageDataDescriptor& descriptor,
       backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context,
       MessageLoop* rasterizer_message_loop);
@@ -166,14 +167,14 @@
   void EnsureInitialized() OVERRIDE;
 
  private:
-  ~SkiaHardwareMultiPlaneImage() OVERRIDE;
+  ~HardwareMultiPlaneImage() OVERRIDE;
 
   const math::Size size_;
 
   render_tree::MultiPlaneImageFormat format_;
 
   // We maintain a single-plane image for each plane of this multi-plane image.
-  scoped_refptr<SkiaHardwareFrontendImage>
+  scoped_refptr<HardwareFrontendImage>
       planes_[render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes];
 };
 
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
index 696ba9c..51f3f6d 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.cc
@@ -36,17 +36,11 @@
 namespace rasterizer {
 namespace skia {
 
-namespace {
-
-const int kMaxSkiaCacheResources = 128;
-const size_t kMaxSkiaCacheBytes = 4 * 1024 * 1024u;
-
-}  // namespace
-
-class SkiaHardwareRasterizer::Impl {
+class HardwareRasterizer::Impl {
  public:
-  explicit Impl(backend::GraphicsContext* graphics_context,
-                int surface_cache_size_in_bytes);
+  Impl(backend::GraphicsContext* graphics_context, int skia_cache_size_in_bytes,
+       int scratch_surface_cache_size_in_bytes,
+       int surface_cache_size_in_bytes);
   ~Impl();
 
   void Submit(const scoped_refptr<render_tree::Node>& render_tree,
@@ -57,7 +51,7 @@
 
  private:
   class CachedScratchSurfaceHolder
-      : public SkiaRenderTreeNodeVisitor::ScratchSurface {
+      : public RenderTreeNodeVisitor::ScratchSurface {
    public:
     CachedScratchSurfaceHolder(ScratchSurfaceCache* cache,
                                const math::Size& size)
@@ -71,7 +65,7 @@
   };
 
   SkSurface* CreateSkSurface(const math::Size& size);
-  scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface(
+  scoped_ptr<RenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface(
       const math::Size& size);
 
   base::ThreadChecker thread_checker_;
@@ -124,12 +118,19 @@
 
 }  // namespace
 
-SkiaHardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context,
-                                   int surface_cache_size_in_bytes)
+HardwareRasterizer::Impl::Impl(backend::GraphicsContext* graphics_context,
+                               int skia_cache_size_in_bytes,
+                               int scratch_surface_cache_size_in_bytes,
+                               int surface_cache_size_in_bytes)
     : graphics_context_(
           base::polymorphic_downcast<backend::GraphicsContextEGL*>(
               graphics_context)) {
-  TRACE_EVENT0("cobalt::renderer", "SkiaHardwareRasterizer::Impl::Impl()");
+  TRACE_EVENT0("cobalt::renderer", "HardwareRasterizer::Impl::Impl()");
+
+  DLOG(INFO) << "skia_cache_size_in_bytes: " << skia_cache_size_in_bytes;
+  DLOG(INFO) << "scratch_surface_cache_size_in_bytes: "
+             << scratch_surface_cache_size_in_bytes;
+  DLOG(INFO) << "surface_cache_size_in_bytes: " << surface_cache_size_in_bytes;
 
   graphics_context_->MakeCurrent();
   // Create a GrContext object that wraps the passed in Cobalt GraphicsContext
@@ -143,19 +144,21 @@
   // rendering shadow effects, gradient effects, and software rendered paths.
   // As we have our own cache for most resources, set it to a much smaller value
   // so Skia doesn't use too much GPU memory.
-  gr_context_->setResourceCacheLimits(
-      kMaxSkiaCacheResources, kMaxSkiaCacheBytes);
+  const int kSkiaCacheMaxResources = 128;
+  gr_context_->setResourceCacheLimits(kSkiaCacheMaxResources,
+                                      skia_cache_size_in_bytes);
 
   base::Callback<SkSurface*(const math::Size&)> create_sk_surface_function =
-      base::Bind(&SkiaHardwareRasterizer::Impl::CreateSkSurface,
+      base::Bind(&HardwareRasterizer::Impl::CreateSkSurface,
                  base::Unretained(this));
 
-  scratch_surface_cache_.emplace(create_sk_surface_function);
+  scratch_surface_cache_.emplace(create_sk_surface_function,
+                                 scratch_surface_cache_size_in_bytes);
 
   // Setup a resource provider for resources to be used with a hardware
   // accelerated Skia rasterizer.
   resource_provider_.reset(
-      new SkiaHardwareResourceProvider(graphics_context_, gr_context_));
+      new HardwareResourceProvider(graphics_context_, gr_context_));
   graphics_context_->ReleaseCurrentContext();
 
   if (surface_cache_size_in_bytes > 0) {
@@ -169,7 +172,7 @@
   }
 }
 
-SkiaHardwareRasterizer::Impl::~Impl() {
+HardwareRasterizer::Impl::~Impl() {
   graphics_context_->MakeCurrent();
   sk_output_surface_.reset(NULL);
   surface_cache_ = base::nullopt;
@@ -179,7 +182,7 @@
   graphics_context_->ReleaseCurrentContext();
 }
 
-void SkiaHardwareRasterizer::Impl::Submit(
+void HardwareRasterizer::Impl::Submit(
     const scoped_refptr<render_tree::Node>& render_tree,
     const scoped_refptr<backend::RenderTarget>& render_target, int options) {
   DCHECK(thread_checker_.CalledOnValidThread());
@@ -224,11 +227,11 @@
   {
     TRACE_EVENT0("cobalt::renderer", "VisitRenderTree");
     // Rasterize the passed in render tree to our hardware render target.
-    SkiaRenderTreeNodeVisitor::CreateScratchSurfaceFunction
+    RenderTreeNodeVisitor::CreateScratchSurfaceFunction
         create_scratch_surface_function =
-            base::Bind(&SkiaHardwareRasterizer::Impl::CreateScratchSurface,
+            base::Bind(&HardwareRasterizer::Impl::CreateScratchSurface,
                        base::Unretained(this));
-    SkiaRenderTreeNodeVisitor visitor(
+    RenderTreeNodeVisitor visitor(
         canvas, &create_scratch_surface_function,
         surface_cache_delegate_ ? &surface_cache_delegate_.value() : NULL,
         surface_cache_ ? &surface_cache_.value() : NULL);
@@ -243,14 +246,12 @@
   graphics_context_->SwapBuffers(render_target_egl);
 }
 
-render_tree::ResourceProvider*
-SkiaHardwareRasterizer::Impl::GetResourceProvider() {
+render_tree::ResourceProvider* HardwareRasterizer::Impl::GetResourceProvider() {
   return resource_provider_.get();
 }
 
-SkSurface* SkiaHardwareRasterizer::Impl::CreateSkSurface(
-    const math::Size& size) {
-  TRACE_EVENT2("cobalt::renderer", "SkiaHardwareRasterizer::CreateSkSurface()",
+SkSurface* HardwareRasterizer::Impl::CreateSkSurface(const math::Size& size) {
+  TRACE_EVENT2("cobalt::renderer", "HardwareRasterizer::CreateSkSurface()",
                "width", size.width(), "height", size.height());
 
   // Create a texture of the specified size.  Then convert it to a render
@@ -284,36 +285,38 @@
   return SkSurface::NewRenderTargetDirect(skia_render_target, &surface_props);
 }
 
-scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface>
-SkiaHardwareRasterizer::Impl::CreateScratchSurface(const math::Size& size) {
-  TRACE_EVENT2("cobalt::renderer",
-               "SkiaHardwareRasterizer::CreateScratchImage()", "width",
-               size.width(), "height", size.height());
+scoped_ptr<RenderTreeNodeVisitor::ScratchSurface>
+HardwareRasterizer::Impl::CreateScratchSurface(const math::Size& size) {
+  TRACE_EVENT2("cobalt::renderer", "HardwareRasterizer::CreateScratchImage()",
+               "width", size.width(), "height", size.height());
 
   scoped_ptr<CachedScratchSurfaceHolder> scratch_surface(
       new CachedScratchSurfaceHolder(&scratch_surface_cache_.value(), size));
   if (scratch_surface->GetSurface()) {
-    return scratch_surface.PassAs<SkiaRenderTreeNodeVisitor::ScratchSurface>();
+    return scratch_surface.PassAs<RenderTreeNodeVisitor::ScratchSurface>();
   } else {
-    return scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface>();
+    return scoped_ptr<RenderTreeNodeVisitor::ScratchSurface>();
   }
 }
 
-SkiaHardwareRasterizer::SkiaHardwareRasterizer(
-    backend::GraphicsContext* graphics_context, int surface_cache_size_in_bytes)
-    : impl_(new Impl(graphics_context, surface_cache_size_in_bytes)) {}
+HardwareRasterizer::HardwareRasterizer(
+    backend::GraphicsContext* graphics_context, int skia_cache_size_in_bytes,
+    int scratch_surface_cache_size_in_bytes, int surface_cache_size_in_bytes)
+    : impl_(new Impl(graphics_context, skia_cache_size_in_bytes,
+                     scratch_surface_cache_size_in_bytes,
+                     surface_cache_size_in_bytes)) {}
 
-SkiaHardwareRasterizer::~SkiaHardwareRasterizer() {}
+HardwareRasterizer::~HardwareRasterizer() {}
 
-void SkiaHardwareRasterizer::Submit(
+void HardwareRasterizer::Submit(
     const scoped_refptr<render_tree::Node>& render_tree,
     const scoped_refptr<backend::RenderTarget>& render_target, int options) {
   TRACE_EVENT0("cobalt::renderer", "Rasterizer::Submit()");
-  TRACE_EVENT0("cobalt::renderer", "SkiaHardwareRasterizer::Submit()");
+  TRACE_EVENT0("cobalt::renderer", "HardwareRasterizer::Submit()");
   impl_->Submit(render_tree, render_target, options);
 }
 
-render_tree::ResourceProvider* SkiaHardwareRasterizer::GetResourceProvider() {
+render_tree::ResourceProvider* HardwareRasterizer::GetResourceProvider() {
   return impl_->GetResourceProvider();
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
index d0d9d96..8807fc3 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_rasterizer.h
@@ -28,22 +28,32 @@
 namespace rasterizer {
 namespace skia {
 
-// This SkiaHardwareRasterizer class represents a rasterizer that will setup
+// This HardwareRasterizer class represents a rasterizer that will setup
 // a Skia hardware rendering context.  When Submit() is called, the passed in
 // render tree will be rasterized using hardware-accelerated Skia.  The
-// SkiaHardwareRasterizer must be constructed on the same thread that Submit()
+// HardwareRasterizer must be constructed on the same thread that Submit()
 // is to be called on.
-class SkiaHardwareRasterizer : public Rasterizer {
+class HardwareRasterizer : public Rasterizer {
  public:
   // The passed in render target will be used to determine the dimensions of
   // the output.  The graphics context will be used to issue commands to the GPU
-  // to blit the final output to the render target.  If |surface_cache_size| is
-  // non-zero, the rasterizer will set itself up with a surface cache such that
-  // expensive render tree nodes seen multiple times will get saved to offscreen
-  // surfaces.
-  explicit SkiaHardwareRasterizer(backend::GraphicsContext* graphics_context,
-                                  int surface_cache_size_in_bytes);
-  virtual ~SkiaHardwareRasterizer();
+  // to blit the final output to the render target.
+  // The value of |skia_cache_size_in_bytes| dictates the maximum amount of
+  // memory that Skia will use to cache the results of certain effects that take
+  // a long time to render, such as shadows.  The results will be reused across
+  // submissions.
+  // The value of |scratch_surface_cache_size_in_bytes| sets an upper limit on
+  // the number of bytes that can be consumed by the scratch surface cache,
+  // a facility that allows temporary surfaces to be reused within the
+  // rasterization of a single frame/submission.
+  // If |surface_cache_size| is non-zero, the rasterizer will set itself up with
+  // a surface cache such that expensive render tree nodes seen multiple times
+  // will get saved to offscreen surfaces.
+  explicit HardwareRasterizer(backend::GraphicsContext* graphics_context,
+                              int skia_cache_size_in_bytes,
+                              int scratch_surface_cache_size_in_bytes,
+                              int surface_cache_size_in_bytes);
+  virtual ~HardwareRasterizer();
 
   // Consume the render tree and output the results to the render target passed
   // into the constructor.
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
index 8dbb7ce..1a1fc84 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.cc
@@ -41,54 +41,52 @@
 namespace rasterizer {
 namespace skia {
 
-SkiaHardwareResourceProvider::SkiaHardwareResourceProvider(
+HardwareResourceProvider::HardwareResourceProvider(
     backend::GraphicsContextEGL* cobalt_context, GrContext* gr_context)
     : cobalt_context_(cobalt_context),
       gr_context_(gr_context),
       self_message_loop_(MessageLoop::current()) {}
 
-bool SkiaHardwareResourceProvider::PixelFormatSupported(
+bool HardwareResourceProvider::PixelFormatSupported(
     render_tree::PixelFormat pixel_format) {
   return pixel_format == render_tree::kPixelFormatRGBA8;
 }
 
-bool SkiaHardwareResourceProvider::AlphaFormatSupported(
+bool HardwareResourceProvider::AlphaFormatSupported(
     render_tree::AlphaFormat alpha_format) {
   return alpha_format == render_tree::kAlphaFormatPremultiplied;
 }
 
-scoped_ptr<ImageData> SkiaHardwareResourceProvider::AllocateImageData(
+scoped_ptr<ImageData> HardwareResourceProvider::AllocateImageData(
     const math::Size& size, render_tree::PixelFormat pixel_format,
     render_tree::AlphaFormat alpha_format) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::AllocateImageData()");
+               "HardwareResourceProvider::AllocateImageData()");
   DCHECK_EQ(render_tree::kPixelFormatRGBA8, pixel_format)
       << "Currently, only RGBA8 is supported.";
 
   DCHECK(PixelFormatSupported(pixel_format));
   DCHECK(AlphaFormatSupported(alpha_format));
 
-  return scoped_ptr<ImageData>(new SkiaHardwareImageData(
+  return scoped_ptr<ImageData>(new HardwareImageData(
       cobalt_context_->system_egl()->AllocateTextureData(
           size, ConvertRenderTreeFormatToGL(pixel_format)),
       pixel_format, alpha_format));
 }
 
-scoped_refptr<Image> SkiaHardwareResourceProvider::CreateImage(
+scoped_refptr<render_tree::Image> HardwareResourceProvider::CreateImage(
     scoped_ptr<ImageData> source_data) {
-  TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::CreateImage()");
-  scoped_ptr<SkiaHardwareImageData> skia_hardware_source_data(
-      base::polymorphic_downcast<SkiaHardwareImageData*>(
-          source_data.release()));
+  TRACE_EVENT0("cobalt::renderer", "HardwareResourceProvider::CreateImage()");
+  scoped_ptr<HardwareImageData> skia_hardware_source_data(
+      base::polymorphic_downcast<HardwareImageData*>(source_data.release()));
   const render_tree::ImageDataDescriptor& descriptor =
       skia_hardware_source_data->GetDescriptor();
 
   DCHECK_EQ(render_tree::kAlphaFormatPremultiplied, descriptor.alpha_format);
 #if defined(COBALT_BUILD_TYPE_DEBUG)
-  SkiaImage::DCheckForPremultipliedAlpha(
-      descriptor.size, descriptor.pitch_in_bytes, descriptor.pixel_format,
-      skia_hardware_source_data->GetMemory());
+  Image::DCheckForPremultipliedAlpha(descriptor.size, descriptor.pitch_in_bytes,
+                                     descriptor.pixel_format,
+                                     skia_hardware_source_data->GetMemory());
 #endif
 
   // Construct a frontend image from this data, which internally will send
@@ -96,56 +94,58 @@
   // backend texture will be constructed, and associated with this frontend
   // texture through a map that will be accessed when the rasterizer visits
   // any subsequently submitted render trees referencing the frontend image.
-  return make_scoped_refptr(new SkiaHardwareFrontendImage(
+  return make_scoped_refptr(new HardwareFrontendImage(
       skia_hardware_source_data.Pass(), cobalt_context_, gr_context_,
       self_message_loop_));
 }
 
-scoped_ptr<RawImageMemory> SkiaHardwareResourceProvider::AllocateRawImageMemory(
+scoped_ptr<RawImageMemory> HardwareResourceProvider::AllocateRawImageMemory(
     size_t size_in_bytes, size_t alignment) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::AllocateRawImageMemory()");
-  return scoped_ptr<RawImageMemory>(new SkiaHardwareRawImageMemory(
+               "HardwareResourceProvider::AllocateRawImageMemory()");
+  return scoped_ptr<RawImageMemory>(new HardwareRawImageMemory(
       cobalt_context_->system_egl()->AllocateRawTextureMemory(size_in_bytes,
                                                               alignment)));
 }
 
-scoped_refptr<Image>
-SkiaHardwareResourceProvider::CreateMultiPlaneImageFromRawMemory(
+scoped_refptr<render_tree::Image>
+HardwareResourceProvider::CreateMultiPlaneImageFromRawMemory(
     scoped_ptr<RawImageMemory> raw_image_memory,
     const render_tree::MultiPlaneImageDataDescriptor& descriptor) {
   TRACE_EVENT0(
       "cobalt::renderer",
-      "SkiaHardwareResourceProvider::CreateMultiPlaneImageFromRawMemory()");
-  DCHECK_EQ(render_tree::kMultiPlaneImageFormatYUV3PlaneBT709,
-            descriptor.image_format())
-      << "Currently we only support 3-plane YUV multi plane images.";
-  DCHECK_EQ(3, descriptor.num_planes());
+      "HardwareResourceProvider::CreateMultiPlaneImageFromRawMemory()");
+  DCHECK((render_tree::kMultiPlaneImageFormatYUV2PlaneBT709 ==
+              descriptor.image_format() &&
+          2 == descriptor.num_planes()) ||
+         (render_tree::kMultiPlaneImageFormatYUV3PlaneBT709 ==
+              descriptor.image_format() &&
+          3 == descriptor.num_planes()))
+      << "Currently we only support 2-plane or 3-plane YUV multi plane images.";
 
-  scoped_ptr<SkiaHardwareRawImageMemory> skia_hardware_raw_image_memory(
-      base::polymorphic_downcast<SkiaHardwareRawImageMemory*>(
+  scoped_ptr<HardwareRawImageMemory> skia_hardware_raw_image_memory(
+      base::polymorphic_downcast<HardwareRawImageMemory*>(
           raw_image_memory.release()));
 
-  return make_scoped_refptr(new SkiaHardwareMultiPlaneImage(
+  return make_scoped_refptr(new HardwareMultiPlaneImage(
       skia_hardware_raw_image_memory.Pass(), descriptor, cobalt_context_,
       gr_context_, self_message_loop_));
 }
 
-bool SkiaHardwareResourceProvider::HasLocalFontFamily(
+bool HardwareResourceProvider::HasLocalFontFamily(
     const char* font_family_name) const {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::HasLocalFontFamily()");
+               "HardwareResourceProvider::HasLocalFontFamily()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name));
   return style_set->count() > 0;
 }
 
-scoped_refptr<render_tree::Typeface>
-SkiaHardwareResourceProvider::GetLocalTypeface(
+scoped_refptr<render_tree::Typeface> HardwareResourceProvider::GetLocalTypeface(
     const char* font_family_name, render_tree::FontStyle font_style) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::GetLocalTypeface()");
+               "HardwareResourceProvider::GetLocalTypeface()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle(
@@ -154,11 +154,11 @@
 }
 
 scoped_refptr<render_tree::Typeface>
-SkiaHardwareResourceProvider::GetCharacterFallbackTypeface(
+HardwareResourceProvider::GetCharacterFallbackTypeface(
     int32 character, render_tree::FontStyle font_style,
     const std::string& language) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::GetCharacterFallbackTypeface()");
+               "HardwareResourceProvider::GetCharacterFallbackTypeface()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkTypeface> typeface(
@@ -168,11 +168,11 @@
 }
 
 scoped_refptr<render_tree::Typeface>
-SkiaHardwareResourceProvider::CreateTypefaceFromRawData(
+HardwareResourceProvider::CreateTypefaceFromRawData(
     scoped_ptr<render_tree::ResourceProvider::RawTypefaceDataVector> raw_data,
     std::string* error_string) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaHardwareResourceProvider::CreateFontFromData()");
+               "HardwareResourceProvider::CreateFontFromData()");
 
   if (raw_data == NULL) {
     *error_string = "No data to process";
@@ -203,7 +203,7 @@
 }
 
 scoped_refptr<render_tree::GlyphBuffer>
-SkiaHardwareResourceProvider::CreateGlyphBuffer(
+HardwareResourceProvider::CreateGlyphBuffer(
     const char16* text_buffer, size_t text_length, const std::string& language,
     bool is_rtl, render_tree::FontProvider* font_provider) {
   return text_shaper_.CreateGlyphBuffer(text_buffer, text_length, language,
@@ -211,13 +211,13 @@
 }
 
 scoped_refptr<render_tree::GlyphBuffer>
-SkiaHardwareResourceProvider::CreateGlyphBuffer(
+HardwareResourceProvider::CreateGlyphBuffer(
     const std::string& utf8_string,
     const scoped_refptr<render_tree::Font>& font) {
   return text_shaper_.CreateGlyphBuffer(utf8_string, font);
 }
 
-float SkiaHardwareResourceProvider::GetTextWidth(
+float HardwareResourceProvider::GetTextWidth(
     const char16* text_buffer, size_t text_length, const std::string& language,
     bool is_rtl, render_tree::FontProvider* font_provider,
     render_tree::FontVector* maybe_used_fonts) {
diff --git a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
index 4d344c4..aec9c85 100644
--- a/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/hardware_resource_provider.h
@@ -33,10 +33,10 @@
 // This class must be thread-safe and capable of creating resources that
 // are to be consumed by this skia hardware rasterizer.  It must be constructed
 // on the thread that will be visiting submitted render trees.
-class SkiaHardwareResourceProvider : public render_tree::ResourceProvider {
+class HardwareResourceProvider : public render_tree::ResourceProvider {
  public:
-  SkiaHardwareResourceProvider(backend::GraphicsContextEGL* cobalt_context,
-                               GrContext* gr_context);
+  HardwareResourceProvider(backend::GraphicsContextEGL* cobalt_context,
+                           GrContext* gr_context);
 
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
   bool AlphaFormatSupported(render_tree::AlphaFormat alpha_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
index 06389ab..62493f3 100644
--- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
+++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.cc
@@ -52,7 +52,7 @@
 
 // Outputs the |width| and |extents| of the glyph with index |codepoint| in
 // |paint|'s font.
-void GetGlyphWidthAndExtents(SkiaFont* skia_font, hb_codepoint_t codepoint,
+void GetGlyphWidthAndExtents(Font* skia_font, hb_codepoint_t codepoint,
                              hb_position_t* width,
                              hb_glyph_extents_t* extents) {
   DCHECK_LE(codepoint, std::numeric_limits<uint16_t>::max());
@@ -78,7 +78,7 @@
 hb_bool_t GetGlyph(hb_font_t* font, void* data, hb_codepoint_t unicode,
                    hb_codepoint_t variation_selector, hb_codepoint_t* glyph,
                    void* user_data) {
-  SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data);
+  Font* skia_font = reinterpret_cast<Font*>(data);
   *glyph = skia_font->GetGlyphForCharacter(unicode);
   return !!*glyph;
 }
@@ -86,7 +86,7 @@
 // Returns the horizontal advance value of the |glyph|.
 hb_position_t GetGlyphHorizontalAdvance(hb_font_t* font, void* data,
                                         hb_codepoint_t glyph, void* user_data) {
-  SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data);
+  Font* skia_font = reinterpret_cast<Font*>(data);
   hb_position_t advance = 0;
 
   GetGlyphWidthAndExtents(skia_font, glyph, &advance, 0);
@@ -100,7 +100,7 @@
   return true;
 }
 
-hb_position_t GetGlyphKerning(SkiaFont* font_data, hb_codepoint_t first_glyph,
+hb_position_t GetGlyphKerning(Font* font_data, hb_codepoint_t first_glyph,
                               hb_codepoint_t second_glyph) {
   SkAutoTUnref<SkTypeface> typeface(font_data->GetSkTypeface());
   const uint16_t glyphs[2] = {static_cast<uint16_t>(first_glyph),
@@ -121,7 +121,7 @@
                                         hb_codepoint_t left_glyph,
                                         hb_codepoint_t right_glyph,
                                         void* user_data) {
-  SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data);
+  Font* skia_font = reinterpret_cast<Font*>(data);
   return GetGlyphKerning(skia_font, left_glyph, right_glyph);
 }
 
@@ -136,7 +136,7 @@
 // Writes the |extents| of |glyph|.
 hb_bool_t GetGlyphExtents(hb_font_t* font, void* data, hb_codepoint_t glyph,
                           hb_glyph_extents_t* extents, void* user_data) {
-  SkiaFont* skia_font = reinterpret_cast<SkiaFont*>(data);
+  Font* skia_font = reinterpret_cast<Font*>(data);
   GetGlyphWidthAndExtents(skia_font, glyph, 0, extents);
   return true;
 }
@@ -222,7 +222,7 @@
 }  // namespace
 
 // Creates a HarfBuzz font from the given Skia font.
-hb_font_t* CreateHarfBuzzFont(SkiaFont* skia_font) {
+hb_font_t* CreateHarfBuzzFont(Font* skia_font) {
   static std::map<SkFontID, HarfBuzzFace> face_caches;
 
   // Retrieve the typeface from the cache. In the case where it does not already
diff --git a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
index 689f159..a37e5c1 100644
--- a/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
+++ b/src/cobalt/renderer/rasterizer/skia/harfbuzz_font.h
@@ -28,9 +28,9 @@
 namespace rasterizer {
 namespace skia {
 
-class SkiaFont;
+class Font;
 
-hb_font_t* CreateHarfBuzzFont(SkiaFont* skia_font);
+hb_font_t* CreateHarfBuzzFont(Font* skia_font);
 
 }  // namespace skia
 }  // namespace rasterizer
diff --git a/src/cobalt/renderer/rasterizer/skia/image.cc b/src/cobalt/renderer/rasterizer/skia/image.cc
index 850007f..ceaf0c5 100644
--- a/src/cobalt/renderer/rasterizer/skia/image.cc
+++ b/src/cobalt/renderer/rasterizer/skia/image.cc
@@ -24,13 +24,15 @@
 namespace rasterizer {
 namespace skia {
 
-void SkiaImage::DCheckForPremultipliedAlpha(
-    const math::Size& dimensions, int source_pitch_in_bytes,
-    render_tree::PixelFormat pixel_format, const uint8_t* source_pixels) {
-  TRACE_EVENT0("cobalt::renderer", "SkiaImage::DCheckForPremultipliedAlpha()");
+void Image::DCheckForPremultipliedAlpha(const math::Size& dimensions,
+                                        int source_pitch_in_bytes,
+                                        render_tree::PixelFormat pixel_format,
+                                        const uint8_t* source_pixels) {
+  TRACE_EVENT0("cobalt::renderer", "Image::DCheckForPremultipliedAlpha()");
   if (pixel_format == render_tree::kPixelFormatY8 ||
       pixel_format == render_tree::kPixelFormatU8 ||
-      pixel_format == render_tree::kPixelFormatV8) {
+      pixel_format == render_tree::kPixelFormatV8 ||
+      pixel_format == render_tree::kPixelFormatUV8) {
     // These formats don't have alpha, so they are trivially good to go.
     return;
   }
diff --git a/src/cobalt/renderer/rasterizer/skia/image.h b/src/cobalt/renderer/rasterizer/skia/image.h
index 839b848..cd2e907 100644
--- a/src/cobalt/renderer/rasterizer/skia/image.h
+++ b/src/cobalt/renderer/rasterizer/skia/image.h
@@ -31,7 +31,7 @@
 // Introduce a base class for both software and hardware Skia images.  They
 // should both be able to return a SkBitmap that can be used in subsequent
 // Skia draw calls.
-class SkiaImage : public render_tree::Image {
+class Image : public render_tree::Image {
  public:
   // Ensures that any queued backend initialization of this image object is
   // completed after this method returns.  This can only be called from the
@@ -43,7 +43,7 @@
   // executed.
   virtual void EnsureInitialized() = 0;
 
-  // Mechanism to allow dynamic type checking on SkiaImage objects.
+  // Mechanism to allow dynamic type checking on Image objects.
   virtual base::TypeId GetTypeId() const = 0;
 
   // A helper function for DCHECKing that given image data is indeed in
@@ -58,25 +58,25 @@
 
 // A single-plane image is an image where all data to describe a single pixel
 // is stored contiguously.  This style of image is by far the most common.
-class SkiaSinglePlaneImage : public SkiaImage {
+class SinglePlaneImage : public Image {
  public:
   virtual const SkBitmap& GetBitmap() const = 0;
 
   base::TypeId GetTypeId() const OVERRIDE {
-    return base::GetTypeId<SkiaSinglePlaneImage>();
+    return base::GetTypeId<SinglePlaneImage>();
   }
 };
 
 // A multi-plane image is one where different channels may have different planes
 // (i.e. sub-images) stored in different regions of memory.  A multi-plane
 // image can be defined in terms of a set of single-plane images.
-class SkiaMultiPlaneImage : public SkiaImage {
+class MultiPlaneImage : public Image {
  public:
   virtual render_tree::MultiPlaneImageFormat GetFormat() const = 0;
   virtual const SkBitmap& GetBitmap(int plane_index) const = 0;
 
   base::TypeId GetTypeId() const OVERRIDE {
-    return base::GetTypeId<SkiaMultiPlaneImage>();
+    return base::GetTypeId<MultiPlaneImage>();
   }
 };
 
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
index cd39b91..6c9c5f6 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.cc
@@ -44,6 +44,7 @@
 #include "cobalt/renderer/rasterizer/skia/font.h"
 #include "cobalt/renderer/rasterizer/skia/glyph_buffer.h"
 #include "cobalt/renderer/rasterizer/skia/image.h"
+#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h"
 #include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/core/SkTypeface.h"
@@ -68,7 +69,7 @@
 namespace rasterizer {
 namespace skia {
 
-SkiaRenderTreeNodeVisitor::SkiaRenderTreeNodeVisitor(
+RenderTreeNodeVisitor::RenderTreeNodeVisitor(
     SkCanvas* render_target,
     const CreateScratchSurfaceFunction* create_scratch_surface_function,
     SurfaceCacheDelegate* surface_cache_delegate,
@@ -84,7 +85,7 @@
     // visitor and our canvas.
     surface_cache_scoped_context_.emplace(
         surface_cache_delegate_, render_target_,
-        base::Bind(&SkiaRenderTreeNodeVisitor::SetRenderTarget,
+        base::Bind(&RenderTreeNodeVisitor::SetRenderTarget,
                    base::Unretained(this)));
   }
 }
@@ -107,7 +108,7 @@
 }
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(
+void RenderTreeNodeVisitor::Visit(
     render_tree::CompositionNode* composition_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(CompositionNode)");
@@ -221,7 +222,7 @@
 
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::RenderFilterViaOffscreenSurface(
+void RenderTreeNodeVisitor::RenderFilterViaOffscreenSurface(
     const render_tree::FilterNode::Builder& filter_node) {
   const SkMatrix& total_matrix_skia = render_target_->getTotalMatrix();
   math::Matrix3F total_matrix = SkiaMatrixToCobalt(total_matrix_skia);
@@ -264,9 +265,9 @@
 
   // Render our source sub-tree into the offscreen surface.
   {
-    SkiaRenderTreeNodeVisitor sub_visitor(
-        canvas, create_scratch_surface_function_, surface_cache_delegate_,
-        surface_cache_, kType_SubVisitor);
+    RenderTreeNodeVisitor sub_visitor(canvas, create_scratch_surface_function_,
+                                      surface_cache_delegate_, surface_cache_,
+                                      kType_SubVisitor);
     filter_node.source->Accept(&sub_visitor);
   }
 
@@ -342,7 +343,7 @@
 }
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
+void RenderTreeNodeVisitor::Visit(render_tree::FilterNode* filter_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(FilterNode)");
 
@@ -460,7 +461,7 @@
   return paint;
 }
 
-void RenderSinglePlaneImage(SkiaSinglePlaneImage* single_plane_image,
+void RenderSinglePlaneImage(SinglePlaneImage* single_plane_image,
                             SkCanvas* render_target,
                             const math::RectF& destination_rect,
                             const math::Matrix3F* local_transform) {
@@ -505,36 +506,51 @@
   }
 }
 
-void RenderMultiPlaneImage(SkiaMultiPlaneImage* multi_plane_image,
+void RenderMultiPlaneImage(MultiPlaneImage* multi_plane_image,
                            SkCanvas* render_target,
                            const math::RectF& destination_rect,
                            const math::Matrix3F* local_transform) {
-  DCHECK_EQ(render_tree::kMultiPlaneImageFormatYUV3PlaneBT709,
-            multi_plane_image->GetFormat());
-
   SkMatrix skia_local_transform = CobaltMatrixToSkia(*local_transform);
 
   const SkBitmap& y_bitmap = multi_plane_image->GetBitmap(0);
+  DCHECK(!y_bitmap.isNull());
   SkMatrix y_matrix = skia_local_transform;
   ConvertLocalTransformMatrixToSkiaShaderFormat(
       math::Size(y_bitmap.width(), y_bitmap.height()), destination_rect,
       &y_matrix);
 
   const SkBitmap& u_bitmap = multi_plane_image->GetBitmap(1);
+  DCHECK(!u_bitmap.isNull());
   SkMatrix u_matrix = skia_local_transform;
   ConvertLocalTransformMatrixToSkiaShaderFormat(
       math::Size(u_bitmap.width(), u_bitmap.height()), destination_rect,
       &u_matrix);
 
-  const SkBitmap& v_bitmap = multi_plane_image->GetBitmap(2);
-  SkMatrix v_matrix = skia_local_transform;
-  ConvertLocalTransformMatrixToSkiaShaderFormat(
-      math::Size(v_bitmap.width(), v_bitmap.height()), destination_rect,
-      &v_matrix);
+  SkAutoTUnref<SkShader> yuv2rgb_shader;
 
-  SkAutoTUnref<SkShader> yuv2rgb_shader(
-      SkNEW_ARGS(SkYUV2RGBShader, (kRec709_SkYUVColorSpace, y_bitmap, y_matrix,
-                                   u_bitmap, u_matrix, v_bitmap, v_matrix)));
+  switch (multi_plane_image->GetFormat()) {
+    case render_tree::kMultiPlaneImageFormatYUV2PlaneBT709:
+      yuv2rgb_shader.reset(SkNEW_ARGS(
+          SkNV122RGBShader,
+          (kRec709_SkYUVColorSpace, y_bitmap, y_matrix, u_bitmap, u_matrix)));
+      break;
+    case render_tree::kMultiPlaneImageFormatYUV3PlaneBT709: {
+      const SkBitmap& v_bitmap = multi_plane_image->GetBitmap(2);
+      DCHECK(!v_bitmap.isNull());
+      SkMatrix v_matrix = skia_local_transform;
+      ConvertLocalTransformMatrixToSkiaShaderFormat(
+          math::Size(v_bitmap.width(), v_bitmap.height()), destination_rect,
+          &v_matrix);
+      yuv2rgb_shader.reset(SkNEW_ARGS(
+          SkYUV2RGBShader, (kRec709_SkYUVColorSpace, y_bitmap, y_matrix,
+                            u_bitmap, u_matrix, v_bitmap, v_matrix)));
+      break;
+    }
+    default: {
+      NOTREACHED() << "Unsupported multi plane image format.";
+      break;
+    }
+  }
 
   SkPaint paint = CreateSkPaintForImageRendering();
   paint.setShader(yuv2rgb_shader);
@@ -543,7 +559,7 @@
 
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
+void RenderTreeNodeVisitor::Visit(render_tree::ImageNode* image_node) {
   // The image_node may contain nothing. For example, when it represents a video
   // element before any frame is decoded.
   if (!image_node->data().source) {
@@ -553,8 +569,8 @@
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(ImageNode)");
 #endif
-  SkiaImage* image =
-      base::polymorphic_downcast<SkiaImage*>(image_node->data().source.get());
+  skia::Image* image =
+      base::polymorphic_downcast<skia::Image*>(image_node->data().source.get());
 
   // Creating an image via a resource provider may simply return a frontend
   // image object and enqueue the initialization of a backend image (to be
@@ -570,16 +586,14 @@
 
   // We issue different skia rasterization commands to render the image
   // depending on whether it's single or multi planed.
-  if (image->GetTypeId() == base::GetTypeId<SkiaSinglePlaneImage>()) {
-    RenderSinglePlaneImage(
-        base::polymorphic_downcast<SkiaSinglePlaneImage*>(image),
-        render_target_, image_node->data().destination_rect,
-        &(image_node->data().local_transform));
-  } else if (image->GetTypeId() == base::GetTypeId<SkiaMultiPlaneImage>()) {
-    RenderMultiPlaneImage(
-        base::polymorphic_downcast<SkiaMultiPlaneImage*>(image), render_target_,
-        image_node->data().destination_rect,
-        &(image_node->data().local_transform));
+  if (image->GetTypeId() == base::GetTypeId<SinglePlaneImage>()) {
+    RenderSinglePlaneImage(base::polymorphic_downcast<SinglePlaneImage*>(image),
+                           render_target_, image_node->data().destination_rect,
+                           &(image_node->data().local_transform));
+  } else if (image->GetTypeId() == base::GetTypeId<MultiPlaneImage>()) {
+    RenderMultiPlaneImage(base::polymorphic_downcast<MultiPlaneImage*>(image),
+                          render_target_, image_node->data().destination_rect,
+                          &(image_node->data().local_transform));
   } else {
     NOTREACHED();
   }
@@ -589,7 +603,7 @@
 #endif
 }
 
-void SkiaRenderTreeNodeVisitor::Visit(
+void RenderTreeNodeVisitor::Visit(
     render_tree::MatrixTransformNode* matrix_transform_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(MatrixTransformNode)");
@@ -621,7 +635,7 @@
 #endif
 }
 
-void SkiaRenderTreeNodeVisitor::Visit(
+void RenderTreeNodeVisitor::Visit(
     render_tree::PunchThroughVideoNode* punch_through_video_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(PunchThroughVideoNode)");
@@ -979,7 +993,7 @@
 
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
+void RenderTreeNodeVisitor::Visit(render_tree::RectNode* rect_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(RectNode)");
 #endif
@@ -1196,7 +1210,7 @@
 
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(
+void RenderTreeNodeVisitor::Visit(
     render_tree::RectShadowNode* rect_shadow_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(RectShadowNode)");
@@ -1238,10 +1252,10 @@
     NOTIMPLEMENTED() << "Cobalt does not yet support text blurs with Gaussian "
                         "sigmas larger than 20.";
   } else {
-    SkiaGlyphBuffer* skia_glyph_buffer =
-        base::polymorphic_downcast<SkiaGlyphBuffer*>(glyph_buffer.get());
+    GlyphBuffer* skia_glyph_buffer =
+        base::polymorphic_downcast<GlyphBuffer*>(glyph_buffer.get());
 
-    SkPaint paint(SkiaFont::GetDefaultSkPaint());
+    SkPaint paint(Font::GetDefaultSkPaint());
     paint.setARGB(color.a() * 255, color.r() * 255, color.g() * 255,
                   color.b() * 255);
 
@@ -1259,7 +1273,7 @@
 }
 }  // namespace
 
-void SkiaRenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
+void RenderTreeNodeVisitor::Visit(render_tree::TextNode* text_node) {
 #if ENABLE_RENDER_TREE_VISITOR_TRACING
   TRACE_EVENT0("cobalt::renderer", "Visit(TextNode)");
 #endif
diff --git a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h
index 96d886e..74f4be2 100644
--- a/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h
+++ b/src/cobalt/renderer/rasterizer/skia/render_tree_node_visitor.h
@@ -37,7 +37,7 @@
 namespace rasterizer {
 namespace skia {
 
-class SkiaRenderTreeNodeVisitor : public render_tree::NodeVisitor {
+class RenderTreeNodeVisitor : public render_tree::NodeVisitor {
  public:
   // This callback may be called by the visitor in order to obtain a SkSurface
   // from which both a SkCanvas can be obtained (for rendering into) and then
@@ -58,11 +58,11 @@
   };
 
   // The create_scratch_surface_function functor object will be saved within
-  // SkiaRenderTreeNodeVisitor, so it must outlive the SkiaRenderTreeNodeVisitor
+  // RenderTreeNodeVisitor, so it must outlive the RenderTreeNodeVisitor
   // object.  If |is_sub_visitor| is set to true, errors will be supported for
   // certain operations such as punch out alpha textures, as it is unfortunately
   // difficult to implement them when rendering to a sub-canvas.
-  SkiaRenderTreeNodeVisitor(
+  RenderTreeNodeVisitor(
       SkCanvas* render_target,
       const CreateScratchSurfaceFunction* create_scratch_surface_function,
       SurfaceCacheDelegate* surface_cache_delegate,
@@ -96,7 +96,7 @@
   base::optional<SurfaceCacheDelegate::ScopedContext>
       surface_cache_scoped_context_;
 
-  DISALLOW_COPY_AND_ASSIGN(SkiaRenderTreeNodeVisitor);
+  DISALLOW_COPY_AND_ASSIGN(RenderTreeNodeVisitor);
 };
 
 }  // namespace skia
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
index 1077388..1b62b9c 100644
--- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
+++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.cc
@@ -29,12 +29,6 @@
 
 namespace {
 
-// We choose this cache size empirically, however exceeding the cache is allowed
-// and won't have any detrimental effects, besides the fact that the cache
-// won't be fully utilized.  It may eventually be nice to allow this to be
-// set as a paramter.
-const size_t kMaxCacheSizeInBytes = 7 * 1024 * 1024;
-
 // Approximate the memory usage of a given surface size.
 size_t ApproximateSurfaceMemory(const math::Size& size) {
   // Here we assume that we use 4 bytes per pixel.
@@ -44,8 +38,10 @@
 }  // namespace
 
 ScratchSurfaceCache::ScratchSurfaceCache(
-    const CreateSkSurfaceFunction& create_sk_surface_function)
+    const CreateSkSurfaceFunction& create_sk_surface_function,
+    int cache_capacity_in_bytes)
     : create_sk_surface_function_(create_sk_surface_function),
+      cache_capacity_in_bytes_(cache_capacity_in_bytes),
       surface_memory_(0) {}
 
 ScratchSurfaceCache::~ScratchSurfaceCache() {
@@ -178,8 +174,9 @@
 void ScratchSurfaceCache::Purge() {
   // Delete surfaces from the front (least recently used) of |unused_surfaces_|
   // until we have deleted all surfaces or lowered our memory usage to under
-  // kMaxCacheSizeInBytes.
-  while (!unused_surfaces_.empty() && surface_memory_ > kMaxCacheSizeInBytes) {
+  // |cache_capacity_in_bytes_|.
+  while (!unused_surfaces_.empty() &&
+         surface_memory_ > cache_capacity_in_bytes_) {
     SkSurface* to_free = unused_surfaces_.front();
     surface_memory_ -= ApproximateSurfaceMemory(
         math::Size(to_free->width(), to_free->height()));
diff --git a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h
index 0e3489c..374cc66 100644
--- a/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h
+++ b/src/cobalt/renderer/rasterizer/skia/scratch_surface_cache.h
@@ -46,8 +46,8 @@
  public:
   typedef base::Callback<SkSurface*(const math::Size&)> CreateSkSurfaceFunction;
 
-  ScratchSurfaceCache(
-      const CreateSkSurfaceFunction& create_sk_surface_function);
+  ScratchSurfaceCache(const CreateSkSurfaceFunction& create_sk_surface_function,
+                      int cache_capacity_in_bytes);
   ~ScratchSurfaceCache();
 
  private:
@@ -70,6 +70,9 @@
   // Called to allocate new SkSurfaces.
   CreateSkSurfaceFunction create_sk_surface_function_;
 
+  // The maximum number of surface bytes that can be stored in the cache.
+  int cache_capacity_in_bytes_;
+
   // We keep track of all surfaces we've handed out using |surface_stack_|.
   // This is mostly for debug checks to verify that surfaces returned to us
   // actually did come from us, and that they are returned in the expected
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
index 068de0a..5695744 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
+++ b/src/cobalt/renderer/rasterizer/skia/skia/config/SkUserConfig.h
@@ -17,6 +17,10 @@
 #ifndef SkUserConfig_DEFINED
 #define SkUserConfig_DEFINED
 
+#if defined(STARBOARD)
+#include "starboard/configuration.h"
+#endif
+
 /*  SkTypes.h, the root of the public header files, does the following trick:
 
     #include <SkPreConfig.h>
@@ -233,4 +237,10 @@
 
 // ===== End Cobalt-specific definitions =====
 
+#if defined(STARBOARD)
+#if SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT)
+#define GR_GL_NO_CONSTANT_ATTRIBUTES 1
+#endif // SB_HAS_QUIRK(GL_NO_CONSTANT_ATTRIBUTE_SUPPORT)
+#endif // defined(STARBOARD)
+
 #endif  // SkUserConfig_DEFINED
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
index 580dc23..08b36f9 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia.gyp
@@ -56,7 +56,7 @@
       'variables': {
         'executable_name': 'filter_fuzz_stub',
       },
-      'includes': [ '../../../../build/deploy.gypi' ],
+      'includes': [ '../../../../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
index 4acd051..93717ca 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
+++ b/src/cobalt/renderer/rasterizer/skia/skia/skia_cobalt.gypi
@@ -18,6 +18,8 @@
   'sources': [
     'config/SkUserConfig.h',
     'egl/src/gpu/cobalt/GrGpuFactory.cc',
+    'src/effects/SkNV122RGBShader.cc',
+    'src/effects/SkNV122RGBShader.h',
     'src/effects/SkYUV2RGBShader.cc',
     'src/effects/SkYUV2RGBShader.h',
     'src/google_logging.cc',
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc
new file mode 100644
index 0000000..712252e
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.cc
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h"
+
+#include <algorithm>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "third_party/skia/include/core/SkShader.h"
+#include "third_party/skia/include/core/SkString.h"
+#include "third_party/skia/include/core/SkWriteBuffer.h"
+#include "third_party/skia/src/core/SkReadBuffer.h"
+#include "third_party/skia/src/gpu/effects/GrYUVtoRGBEffect.h"
+
+SkNV122RGBShader::SkNV122RGBShader(SkYUVColorSpace color_space,
+                                   const SkBitmap& y_bitmap,
+                                   const SkMatrix& y_matrix,
+                                   const SkBitmap& uv_bitmap,
+                                   const SkMatrix& uv_matrix)
+    : color_space_(color_space),
+      y_bitmap_(y_bitmap),
+      y_matrix_(y_matrix),
+      uv_bitmap_(uv_bitmap),
+      uv_matrix_(uv_matrix) {
+  DCHECK(!y_bitmap_.isNull());
+  DCHECK(!uv_bitmap_.isNull());
+  InitializeShaders();
+}
+
+void SkNV122RGBShader::InitializeShaders() {
+  y_shader_ =
+      SkShader::CreateBitmapShader(y_bitmap_, SkShader::kClamp_TileMode,
+                                   SkShader::kClamp_TileMode, &y_matrix_);
+  DCHECK(y_shader_);
+
+  uv_shader_ =
+      SkShader::CreateBitmapShader(uv_bitmap_, SkShader::kClamp_TileMode,
+                                   SkShader::kClamp_TileMode, &uv_matrix_);
+  DCHECK(uv_shader_);
+}
+
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
+SkNV122RGBShader::SkNV122RGBShader(SkReadBuffer& buffer) : INHERITED(buffer) {
+  color_space_ = static_cast<SkYUVColorSpace>(buffer.readInt());
+  buffer.readBitmap(&y_bitmap_);
+  buffer.readMatrix(&y_matrix_);
+  buffer.readBitmap(&uv_bitmap_);
+  buffer.readMatrix(&uv_matrix_);
+  InitializeShaders();
+}
+#endif
+
+SkNV122RGBShader::~SkNV122RGBShader() {
+  y_shader_->unref();
+  uv_shader_->unref();
+}
+
+SkFlattenable* SkNV122RGBShader::CreateProc(SkReadBuffer& buffer) {
+  SkYUVColorSpace color_space = static_cast<SkYUVColorSpace>(buffer.readInt());
+
+  SkBitmap y_bitmap;
+  if (!buffer.readBitmap(&y_bitmap)) {
+    return NULL;
+  }
+  y_bitmap.setImmutable();
+  SkMatrix y_matrix;
+  buffer.readMatrix(&y_matrix);
+
+  SkBitmap uv_bitmap;
+  if (!buffer.readBitmap(&uv_bitmap)) {
+    return NULL;
+  }
+  uv_bitmap.setImmutable();
+  SkMatrix uv_matrix;
+  buffer.readMatrix(&uv_matrix);
+
+  return SkNEW_ARGS(SkNV122RGBShader,
+                    (color_space, y_bitmap, y_matrix, uv_bitmap, uv_matrix));
+}
+
+void SkNV122RGBShader::flatten(SkWriteBuffer& buffer) const {
+  buffer.writeInt(color_space_);
+  buffer.writeBitmap(y_bitmap_);
+  buffer.writeMatrix(y_matrix_);
+  buffer.writeBitmap(uv_bitmap_);
+  buffer.writeMatrix(uv_matrix_);
+}
+
+uint32_t SkNV122RGBShader::NV122RGBShaderContext::getFlags() const { return 0; }
+
+SkShader::Context* SkNV122RGBShader::onCreateContext(const ContextRec& rec,
+                                                     void* storage) const {
+  char* shaderContextStorage =
+      static_cast<char*>(storage) + sizeof(NV122RGBShaderContext);
+  SkShader::Context* y_shader_context =
+      y_shader_->createContext(rec, shaderContextStorage);
+  DCHECK(y_shader_context);
+  shaderContextStorage += y_shader_->contextSize();
+  SkShader::Context* uv_shader_context =
+      uv_shader_->createContext(rec, shaderContextStorage);
+  DCHECK(uv_shader_context);
+
+  return SkNEW_PLACEMENT_ARGS(
+      storage, NV122RGBShaderContext,
+      (color_space_, *this, y_shader_context, uv_shader_context, rec));
+}
+
+size_t SkNV122RGBShader::contextSize() const {
+  return sizeof(NV122RGBShaderContext) + y_shader_->contextSize() +
+         uv_shader_->contextSize();
+}
+
+SkNV122RGBShader::NV122RGBShaderContext::NV122RGBShaderContext(
+    SkYUVColorSpace color_space, const SkNV122RGBShader& yuv2rgb_shader,
+    SkShader::Context* y_shader_context, SkShader::Context* uv_shader_context,
+    const ContextRec& rec)
+    : INHERITED(yuv2rgb_shader, rec),
+      color_space_(color_space),
+      y_shader_context_(y_shader_context),
+      uv_shader_context_(uv_shader_context) {}
+
+SkNV122RGBShader::NV122RGBShaderContext::~NV122RGBShaderContext() {
+  y_shader_context_->~Context();
+  uv_shader_context_->~Context();
+}
+
+void SkNV122RGBShader::NV122RGBShaderContext::shadeSpan(int x, int y,
+                                                        SkPMColor result[],
+                                                        int count) {
+  static const int kPixelCountPerSpan = 64;
+  SkPMColor y_values[kPixelCountPerSpan];
+  SkPMColor uv_values[kPixelCountPerSpan];
+
+  DCHECK_EQ(kRec709_SkYUVColorSpace, color_space_)
+      << "Currently we only support the BT.709 YUV colorspace.";
+
+  do {
+    int count_in_chunk =
+        count > kPixelCountPerSpan ? kPixelCountPerSpan : count;
+
+    y_shader_context_->shadeSpan(x, y, y_values, count_in_chunk);
+    uv_shader_context_->shadeSpan(x, y, uv_values, count_in_chunk);
+
+    for (int i = 0; i < count_in_chunk; ++i) {
+      int32_t y_value = SkColorGetA(y_values[i]) - 16;
+      int32_t u_value = SkColorGetB(uv_values[i]) - 128;
+      int32_t v_value = SkColorGetA(uv_values[i]) - 128;
+
+      const float kA = 1.164f;
+      const float kB = -0.213f;
+      const float kC = 2.112f;
+      const float kD = 1.793f;
+      const float kE = -0.533f;
+      int32_t r_unclamped = static_cast<int32_t>(kA * y_value + kD * v_value);
+      int32_t g_unclamped =
+          static_cast<int32_t>(kA * y_value + kB * u_value + kE * v_value);
+      int32_t b_unclamped = static_cast<int32_t>(kA * y_value + kC * u_value);
+
+      int32_t r_clamped =
+          std::min<int32_t>(255, std::max<int32_t>(0, r_unclamped));
+      int32_t g_clamped =
+          std::min<int32_t>(255, std::max<int32_t>(0, g_unclamped));
+      int32_t b_clamped =
+          std::min<int32_t>(255, std::max<int32_t>(0, b_unclamped));
+
+      result[i] = SkPackARGB32NoCheck(255, r_clamped, g_clamped, b_clamped);
+    }
+    result += count_in_chunk;
+    x += count_in_chunk;
+    count -= count_in_chunk;
+  } while (count > 0);
+}
+
+void SkNV122RGBShader::NV122RGBShaderContext::shadeSpan16(int x, int y,
+                                                          uint16_t result[],
+                                                          int count) {
+  NOTREACHED();
+}
+
+#ifndef SK_IGNORE_TO_STRING
+void SkNV122RGBShader::toString(SkString* str) const {
+  str->append("SkNV122RGBShader: (");
+
+  str->append("Y Shader: ");
+  y_shader_->toString(str);
+  str->append("UV Shader: ");
+  uv_shader_->toString(str);
+
+  this->INHERITED::toString(str);
+
+  str->append(")");
+}
+#endif  // SK_IGNORE_TO_STRING
+
+#if SK_SUPPORT_GPU
+
+bool SkNV122RGBShader::asFragmentProcessor(GrContext*, const SkPaint& paint,
+                                           const SkMatrix* localMatrix,
+                                           GrColor*,
+                                           GrFragmentProcessor** fp) const {
+  // Code snippet taken from SkBitmapProcShader::asFragmentProcessor().
+  SkMatrix matrix;
+  matrix.setIDiv(y_bitmap_.width(), y_bitmap_.height());
+
+  SkMatrix lmInverse;
+  if (!y_shader_->getLocalMatrix().invert(&lmInverse)) {
+    return false;
+  }
+  if (localMatrix) {
+    SkMatrix inv;
+    if (!localMatrix->invert(&inv)) {
+      return false;
+    }
+    lmInverse.postConcat(inv);
+  }
+  matrix.preConcat(lmInverse);
+
+  GrTextureParams::FilterMode filter_mode =
+      paint.getFilterLevel() == SkPaint::kNone_FilterLevel
+          ? GrTextureParams::kNone_FilterMode
+          : GrTextureParams::kBilerp_FilterMode;
+  GrTextureParams texture_params;
+  texture_params.setFilterMode(filter_mode);
+
+  *fp = GrYUVtoRGBEffect::Create(y_bitmap_.getTexture(),
+                                 uv_bitmap_.getTexture(), NULL, matrix,
+                                 texture_params, kRec709_SkYUVColorSpace, true);
+  return true;
+}
+
+#endif  // SK_SUPPORT_GPU
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h
new file mode 100644
index 0000000..f7d6545
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkNV122RGBShader.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_
+#define COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_
+
+#include "SkShader.h"
+
+class SkNV122RGBShader : public SkShader {
+ public:
+  SkNV122RGBShader(SkYUVColorSpace color_space, const SkBitmap& y_bitmap,
+                   const SkMatrix& y_matrix, const SkBitmap& uv_bitmap,
+                   const SkMatrix& uv_matrix);
+  virtual ~SkNV122RGBShader();
+
+  virtual size_t contextSize() const SK_OVERRIDE;
+
+  class NV122RGBShaderContext : public SkShader::Context {
+   public:
+    // Takes ownership of shaderContext and calls its destructor.
+    NV122RGBShaderContext(SkYUVColorSpace color_space,
+                          const SkNV122RGBShader& yuv2rgb_shader,
+                          SkShader::Context* y_shader_context,
+                          SkShader::Context* uv_shader_context,
+                          const ContextRec& rec);
+    virtual ~NV122RGBShaderContext();
+
+    virtual uint32_t getFlags() const SK_OVERRIDE;
+
+    virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+    virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
+
+    virtual void set3DMask(const SkMask* mask) SK_OVERRIDE {
+      // forward to our proxy
+      y_shader_context_->set3DMask(mask);
+      uv_shader_context_->set3DMask(mask);
+    }
+
+   private:
+    SkYUVColorSpace color_space_;
+
+    SkShader::Context* y_shader_context_;
+    SkShader::Context* uv_shader_context_;
+
+    typedef SkShader::Context INHERITED;
+  };
+
+#if SK_SUPPORT_GPU
+  bool asFragmentProcessor(GrContext*, const SkPaint&, const SkMatrix*,
+                           GrColor*, GrFragmentProcessor**) const SK_OVERRIDE;
+#endif
+
+  SK_TO_STRING_OVERRIDE()
+  SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkNV122RGBShader)
+
+ protected:
+#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
+  explicit SkNV122RGBShader(SkReadBuffer&);
+#endif
+  virtual void flatten(SkWriteBuffer&) const SK_OVERRIDE;
+  virtual Context* onCreateContext(const ContextRec&,
+                                   void* storage) const SK_OVERRIDE;
+
+ private:
+  void InitializeShaders();
+
+  SkYUVColorSpace color_space_;
+
+  SkBitmap y_bitmap_;
+  SkMatrix y_matrix_;
+  SkShader* y_shader_;
+
+  SkBitmap uv_bitmap_;
+  SkMatrix uv_matrix_;
+  SkShader* uv_shader_;
+
+  typedef SkShader INHERITED;
+};
+
+#endif  // COBALT_RENDERER_RASTERIZER_SKIA_SKIA_SRC_EFFECTS_SKNV122RGBSHADER_H_
diff --git a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc
index 4635426..aaf6bbe 100644
--- a/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc
+++ b/src/cobalt/renderer/rasterizer/skia/skia/src/effects/SkYUV2RGBShader.cc
@@ -35,6 +35,9 @@
     y_bitmap_(y_bitmap), y_matrix_(y_matrix),
     u_bitmap_(u_bitmap), u_matrix_(u_matrix),
     v_bitmap_(v_bitmap), v_matrix_(v_matrix) {
+  DCHECK(!y_bitmap_.isNull());
+  DCHECK(!u_bitmap_.isNull());
+  DCHECK(!v_bitmap_.isNull());
   InitializeShaders();
 }
 
@@ -42,14 +45,17 @@
   y_shader_ = SkShader::CreateBitmapShader(
       y_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
       &y_matrix_);
+  DCHECK(y_shader_);
 
   u_shader_ = SkShader::CreateBitmapShader(
       u_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
       &u_matrix_);
+  DCHECK(u_shader_);
 
   v_shader_ = SkShader::CreateBitmapShader(
       v_bitmap_, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
       &v_matrix_);
+  DCHECK(v_shader_);
 }
 
 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
@@ -124,12 +130,15 @@
       static_cast<char*>(storage) + sizeof(YUV2RGBShaderContext);
   SkShader::Context* y_shader_context =
       y_shader_->createContext(rec, shaderContextStorage);
+  DCHECK(y_shader_context);
   shaderContextStorage += y_shader_->contextSize();
   SkShader::Context* u_shader_context =
       u_shader_->createContext(rec, shaderContextStorage);
+  DCHECK(u_shader_context);
   shaderContextStorage += u_shader_->contextSize();
   SkShader::Context* v_shader_context =
       v_shader_->createContext(rec, shaderContextStorage);
+  DCHECK(v_shader_context);
 
   return SkNEW_PLACEMENT_ARGS(
     storage, YUV2RGBShaderContext,
@@ -262,7 +271,7 @@
 
   *fp = GrYUVtoRGBEffect::Create(y_bitmap_.getTexture(), u_bitmap_.getTexture(),
                                  v_bitmap_.getTexture(), matrix, texture_params,
-                                 kRec709_SkYUVColorSpace);
+                                 kRec709_SkYUVColorSpace, false);
   return true;
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/software_image.cc b/src/cobalt/renderer/rasterizer/skia/software_image.cc
index 3b87f8d..5f68cde 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_image.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_image.cc
@@ -24,87 +24,115 @@
 namespace rasterizer {
 namespace skia {
 
-SkiaSoftwareImageData::SkiaSoftwareImageData(
-    const math::Size& size, render_tree::PixelFormat pixel_format,
-    render_tree::AlphaFormat alpha_format)
+SoftwareImageData::SoftwareImageData(const math::Size& size,
+                                     render_tree::PixelFormat pixel_format,
+                                     render_tree::AlphaFormat alpha_format)
     : descriptor_(size, pixel_format, alpha_format,
                   size.width() * render_tree::BytesPerPixel(pixel_format)),
       pixel_data_(new uint8_t[size.height() * descriptor_.pitch_in_bytes]) {}
 
-const render_tree::ImageDataDescriptor& SkiaSoftwareImageData::GetDescriptor()
+const render_tree::ImageDataDescriptor& SoftwareImageData::GetDescriptor()
     const {
   return descriptor_;
 }
 
-uint8_t* SkiaSoftwareImageData::GetMemory() { return pixel_data_.get(); }
+uint8_t* SoftwareImageData::GetMemory() { return pixel_data_.get(); }
 
-scoped_array<uint8_t> SkiaSoftwareImageData::PassPixelData() {
+scoped_array<uint8_t> SoftwareImageData::PassPixelData() {
   return pixel_data_.Pass();
 }
 
-SkiaSoftwareImage::SkiaSoftwareImage(
-    scoped_ptr<SkiaSoftwareImageData> source_data) {
+SoftwareImage::SoftwareImage(scoped_ptr<SoftwareImageData> source_data) {
   owned_pixel_data_ = source_data->PassPixelData();
   Initialize(owned_pixel_data_.get(), source_data->GetDescriptor());
 }
 
-SkiaSoftwareImage::SkiaSoftwareImage(
+SoftwareImage::SoftwareImage(
     uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) {
   Initialize(source_data, descriptor);
 }
 
-void SkiaSoftwareImage::Initialize(
+namespace {
+// Converts UV8 texture data to an ARGB SkBitmap where the original U channel is
+// found in the B channel, the original V channel is found in the A channel, and
+// the R and G channels are zeroed out.
+void ConvertUV8ToARGBSkBitmap(
+    uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor,
+    SkBitmap* bitmap) {
+  bitmap->allocN32Pixels(descriptor.size.width(), descriptor.size.height());
+  int row_pixels_dest = bitmap->rowBytes() / bitmap->bytesPerPixel();
+
+  bitmap->lockPixels();
+  uint8_t* current_src = source_data;
+  SkColor* current_dest = static_cast<SkColor*>(bitmap->getPixels());
+  for (int row = 0; row < descriptor.size.height(); ++row) {
+    for (int column = 0; column < descriptor.size.width(); ++column) {
+      current_dest[column] = SkColorSetARGBMacro(
+          current_src[column * 2 + 1], 0, 0, current_src[column * 2 + 0]);
+    }
+    current_dest += row_pixels_dest;
+    current_src += descriptor.pitch_in_bytes;
+  }
+  bitmap->unlockPixels();
+}
+}  // namespace
+
+void SoftwareImage::Initialize(
     uint8_t* source_data, const render_tree::ImageDataDescriptor& descriptor) {
   SkAlphaType skia_alpha_format =
       RenderTreeAlphaFormatToSkia(descriptor.alpha_format);
   DCHECK_EQ(kPremul_SkAlphaType, skia_alpha_format);
 
-  // Convert our incoming pixel data from unpremultiplied alpha to
-  // premultiplied alpha format, which is what Skia expects.
-  SkImageInfo premul_image_info =
-      SkImageInfo::Make(descriptor.size.width(), descriptor.size.height(),
-                        RenderTreeSurfaceFormatToSkia(descriptor.pixel_format),
-                        skia_alpha_format);
+  size_ = descriptor.size;
 
+  if (descriptor.pixel_format == render_tree::kPixelFormatUV8) {
+    // Convert UV8 to ARGB because Skia does not support any two-channel
+    // formats.  This of course is not efficient, but efficiency in the software
+    // renderer is not as important as completeness and correctness.
+    ConvertUV8ToARGBSkBitmap(source_data, descriptor, &bitmap_);
+  } else {
 // Check that the incoming pixel data is indeed in premultiplied alpha
 // format.
 #if !defined(NDEBUG)
-  SkiaImage::DCheckForPremultipliedAlpha(descriptor.size,
-                                         descriptor.pitch_in_bytes,
-                                         descriptor.pixel_format, source_data);
+    Image::DCheckForPremultipliedAlpha(descriptor.size,
+                                       descriptor.pitch_in_bytes,
+                                       descriptor.pixel_format, source_data);
 #endif
-  bitmap_.installPixels(premul_image_info, source_data,
-                        descriptor.pitch_in_bytes);
-
-  size_ = descriptor.size;
+    // Convert our incoming pixel data from unpremultiplied alpha to
+    // premultiplied alpha format, which is what Skia expects.
+    SkImageInfo premul_image_info = SkImageInfo::Make(
+        descriptor.size.width(), descriptor.size.height(),
+        RenderTreeSurfaceFormatToSkia(descriptor.pixel_format),
+        skia_alpha_format);
+    bitmap_.installPixels(premul_image_info, source_data,
+                          descriptor.pitch_in_bytes);
+  }
 }
 
-SkiaSoftwareRawImageMemory::SkiaSoftwareRawImageMemory(size_t size_in_bytes,
-                                                       size_t alignment)
+SoftwareRawImageMemory::SoftwareRawImageMemory(size_t size_in_bytes,
+                                               size_t alignment)
     : size_in_bytes_(size_in_bytes),
       pixel_data_(
           static_cast<uint8_t*>(base::AlignedAlloc(size_in_bytes, alignment))) {
 }
 
-size_t SkiaSoftwareRawImageMemory::GetSizeInBytes() const {
-  return size_in_bytes_;
-}
+size_t SoftwareRawImageMemory::GetSizeInBytes() const { return size_in_bytes_; }
 
-uint8_t* SkiaSoftwareRawImageMemory::GetMemory() { return pixel_data_.get(); }
+uint8_t* SoftwareRawImageMemory::GetMemory() { return pixel_data_.get(); }
 
 scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree>
-SkiaSoftwareRawImageMemory::PassPixelData() {
+SoftwareRawImageMemory::PassPixelData() {
   return pixel_data_.Pass();
 }
 
-SkiaSoftwareMultiPlaneImage::SkiaSoftwareMultiPlaneImage(
-    scoped_ptr<SkiaSoftwareRawImageMemory> raw_image_memory,
+SoftwareMultiPlaneImage::SoftwareMultiPlaneImage(
+    scoped_ptr<SoftwareRawImageMemory> raw_image_memory,
     const render_tree::MultiPlaneImageDataDescriptor& descriptor)
     : size_(descriptor.GetPlaneDescriptor(0).size),
       format_(descriptor.image_format()),
       owned_pixel_data_(raw_image_memory->PassPixelData()) {
   for (int i = 0; i < descriptor.num_planes(); ++i) {
-    planes_[i] = new SkiaSoftwareImage(
+    planes_[i] = new SoftwareImage(
         owned_pixel_data_.get() + descriptor.GetPlaneOffset(i),
         descriptor.GetPlaneDescriptor(i));
   }
diff --git a/src/cobalt/renderer/rasterizer/skia/software_image.h b/src/cobalt/renderer/rasterizer/skia/software_image.h
index f40a813..37bd1ad 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_image.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_image.h
@@ -29,11 +29,11 @@
 namespace rasterizer {
 namespace skia {
 
-class SkiaSoftwareImageData : public render_tree::ImageData {
+class SoftwareImageData : public render_tree::ImageData {
  public:
-  SkiaSoftwareImageData(const math::Size& size,
-                        render_tree::PixelFormat pixel_format,
-                        render_tree::AlphaFormat alpha_format);
+  SoftwareImageData(const math::Size& size,
+                    render_tree::PixelFormat pixel_format,
+                    render_tree::AlphaFormat alpha_format);
 
   const render_tree::ImageDataDescriptor& GetDescriptor() const OVERRIDE;
   uint8_t* GetMemory() OVERRIDE;
@@ -45,12 +45,11 @@
   scoped_array<uint8_t> pixel_data_;
 };
 
-class SkiaSoftwareImage : public SkiaSinglePlaneImage {
+class SoftwareImage : public SinglePlaneImage {
  public:
-  explicit SkiaSoftwareImage(
-      scoped_ptr<SkiaSoftwareImageData> source_data);
-  SkiaSoftwareImage(uint8_t* source_data,
-                    const render_tree::ImageDataDescriptor& descriptor);
+  explicit SoftwareImage(scoped_ptr<SoftwareImageData> source_data);
+  SoftwareImage(uint8_t* source_data,
+                const render_tree::ImageDataDescriptor& descriptor);
 
   const math::Size& GetSize() const OVERRIDE { return size_; }
 
@@ -67,9 +66,9 @@
   math::Size size_;
 };
 
-class SkiaSoftwareRawImageMemory : public render_tree::RawImageMemory {
+class SoftwareRawImageMemory : public render_tree::RawImageMemory {
  public:
-  SkiaSoftwareRawImageMemory(size_t size_in_bytes, size_t alignment);
+  SoftwareRawImageMemory(size_t size_in_bytes, size_t alignment);
 
   size_t GetSizeInBytes() const OVERRIDE;
   uint8_t* GetMemory() OVERRIDE;
@@ -81,10 +80,10 @@
   scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> pixel_data_;
 };
 
-class SkiaSoftwareMultiPlaneImage : public SkiaMultiPlaneImage {
+class SoftwareMultiPlaneImage : public MultiPlaneImage {
  public:
-  SkiaSoftwareMultiPlaneImage(
-      scoped_ptr<SkiaSoftwareRawImageMemory> raw_image_memory,
+  SoftwareMultiPlaneImage(
+      scoped_ptr<SoftwareRawImageMemory> raw_image_memory,
       const render_tree::MultiPlaneImageDataDescriptor& descriptor);
 
   const math::Size& GetSize() const OVERRIDE { return size_; }
@@ -104,7 +103,7 @@
 
   scoped_ptr_malloc<uint8_t, base::ScopedPtrAlignedFree> owned_pixel_data_;
 
-  scoped_refptr<SkiaSoftwareImage>
+  scoped_refptr<SoftwareImage>
       planes_[render_tree::MultiPlaneImageDataDescriptor::kMaxPlanes];
 };
 
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
index 040cc37..208d179 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.cc
@@ -37,8 +37,7 @@
       SkImageInfo::MakeN32Premul(size.width(), size.height()));
 }
 
-class SoftwareScratchSurface
-    : public SkiaRenderTreeNodeVisitor::ScratchSurface {
+class SoftwareScratchSurface : public RenderTreeNodeVisitor::ScratchSurface {
  public:
   explicit SoftwareScratchSurface(const math::Size& size)
       : surface_(CreateScratchSkSurface(size)) {}
@@ -48,11 +47,11 @@
   SkAutoTUnref<SkSurface> surface_;
 };
 
-scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface(
+scoped_ptr<RenderTreeNodeVisitor::ScratchSurface> CreateScratchSurface(
     const math::Size& size) {
   TRACE_EVENT2("cobalt::renderer", "CreateScratchSurface()", "width",
                size.width(), "height", size.height());
-  return scoped_ptr<SkiaRenderTreeNodeVisitor::ScratchSurface>(
+  return scoped_ptr<RenderTreeNodeVisitor::ScratchSurface>(
       new SoftwareScratchSurface(size));
 }
 
@@ -60,7 +59,7 @@
 
 }  // namespace
 
-class SkiaSoftwareRasterizer::Impl {
+class SoftwareRasterizer::Impl {
  public:
   explicit Impl(int surface_cache_size);
 
@@ -78,10 +77,9 @@
   base::optional<common::SurfaceCache> surface_cache_;
 };
 
-SkiaSoftwareRasterizer::Impl::Impl(int surface_cache_size)
-    : resource_provider_(new SkiaSoftwareResourceProvider()) {
-  TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareRasterizer::SkiaSoftwareRasterizer()");
+SoftwareRasterizer::Impl::Impl(int surface_cache_size)
+    : resource_provider_(new SoftwareResourceProvider()) {
+  TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::SoftwareRasterizer()");
 
   if (surface_cache_size > 0) {
     // Software surfaces don't have size limits, so this is set to an arbitrary
@@ -96,11 +94,11 @@
   }
 }
 
-void SkiaSoftwareRasterizer::Impl::Submit(
+void SoftwareRasterizer::Impl::Submit(
     const scoped_refptr<render_tree::Node>& render_tree,
     SkCanvas* render_target) {
   TRACE_EVENT0("cobalt::renderer", "Rasterizer::Submit()");
-  TRACE_EVENT0("cobalt::renderer", "SkiaSoftwareRasterizer::Submit()");
+  TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::Submit()");
 
   // Update our surface cache to do per-frame calculations such as deciding
   // which render tree nodes are candidates for caching in this upcoming
@@ -114,9 +112,9 @@
 
     // Create the rasterizer and setup its render target to the bitmap we have
     // just created above.
-    SkiaRenderTreeNodeVisitor::CreateScratchSurfaceFunction
+    RenderTreeNodeVisitor::CreateScratchSurfaceFunction
         create_scratch_surface_function = base::Bind(&CreateScratchSurface);
-    SkiaRenderTreeNodeVisitor visitor(
+    RenderTreeNodeVisitor visitor(
         render_target, &create_scratch_surface_function,
         surface_cache_delegate_ ? &surface_cache_delegate_.value() : NULL,
         surface_cache_ ? &surface_cache_.value() : NULL);
@@ -127,27 +125,25 @@
   }
 }
 
-render_tree::ResourceProvider*
-SkiaSoftwareRasterizer::Impl::GetResourceProvider() {
-  TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareRasterizer::GetResourceProvider()");
+render_tree::ResourceProvider* SoftwareRasterizer::Impl::GetResourceProvider() {
+  TRACE_EVENT0("cobalt::renderer", "SoftwareRasterizer::GetResourceProvider()");
   return resource_provider_.get();
 }
 
-SkiaSoftwareRasterizer::SkiaSoftwareRasterizer(int surface_cache_size)
+SoftwareRasterizer::SoftwareRasterizer(int surface_cache_size)
     : impl_(new Impl(surface_cache_size)) {}
 
-SkiaSoftwareRasterizer::~SkiaSoftwareRasterizer() {}
+SoftwareRasterizer::~SoftwareRasterizer() {}
 
 // Consume the render tree and output the results to the render target passed
 // into the constructor.
-void SkiaSoftwareRasterizer::Submit(
+void SoftwareRasterizer::Submit(
     const scoped_refptr<render_tree::Node>& render_tree,
     SkCanvas* render_target) {
   impl_->Submit(render_tree, render_target);
 }
 
-render_tree::ResourceProvider* SkiaSoftwareRasterizer::GetResourceProvider() {
+render_tree::ResourceProvider* SoftwareRasterizer::GetResourceProvider() {
   return impl_->GetResourceProvider();
 }
 
diff --git a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
index 6d8f24e..7ecaf06 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_rasterizer.h
@@ -33,12 +33,12 @@
 // it can be used within a wrapper class that does implement it.
 // This class focuses on rendering a render tree to a SkCanvas object,
 // so a platform-specific rasterizer::Rasterizer implementation could wrap
-// this object and after calling SkiaSoftwareRasterizer::Submit(), the wrapper
+// this object and after calling SoftwareRasterizer::Submit(), the wrapper
 // class can send the results to a display or render target.
-class SkiaSoftwareRasterizer {
+class SoftwareRasterizer {
  public:
-  explicit SkiaSoftwareRasterizer(int surface_cache_size);
-  ~SkiaSoftwareRasterizer();
+  explicit SoftwareRasterizer(int surface_cache_size);
+  ~SoftwareRasterizer();
 
   // Consume the render tree and output the results to the render target passed
   // into the constructor.
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
index 5277d6b..abe46c6 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.cc
@@ -37,80 +37,76 @@
 namespace rasterizer {
 namespace skia {
 
-bool SkiaSoftwareResourceProvider::PixelFormatSupported(
+bool SoftwareResourceProvider::PixelFormatSupported(
     render_tree::PixelFormat pixel_format) {
   return RenderTreeSurfaceFormatToSkia(pixel_format) == kN32_SkColorType;
 }
 
-bool SkiaSoftwareResourceProvider::AlphaFormatSupported(
+bool SoftwareResourceProvider::AlphaFormatSupported(
     render_tree::AlphaFormat alpha_format) {
   return alpha_format == render_tree::kAlphaFormatPremultiplied;
 }
 
-scoped_ptr<ImageData> SkiaSoftwareResourceProvider::AllocateImageData(
+scoped_ptr<ImageData> SoftwareResourceProvider::AllocateImageData(
     const math::Size& size, render_tree::PixelFormat pixel_format,
     render_tree::AlphaFormat alpha_format) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::AllocateImageData()");
+               "SoftwareResourceProvider::AllocateImageData()");
   DCHECK(PixelFormatSupported(pixel_format));
   DCHECK(AlphaFormatSupported(alpha_format));
   return scoped_ptr<ImageData>(
-      new SkiaSoftwareImageData(size, pixel_format, alpha_format));
+      new SoftwareImageData(size, pixel_format, alpha_format));
 }
 
-scoped_refptr<render_tree::Image> SkiaSoftwareResourceProvider::CreateImage(
+scoped_refptr<render_tree::Image> SoftwareResourceProvider::CreateImage(
     scoped_ptr<ImageData> source_data) {
-  TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::CreateImage()");
-  scoped_ptr<SkiaSoftwareImageData> skia_source_data(
-      base::polymorphic_downcast<SkiaSoftwareImageData*>(
-          source_data.release()));
+  TRACE_EVENT0("cobalt::renderer", "SoftwareResourceProvider::CreateImage()");
+  scoped_ptr<SoftwareImageData> skia_source_data(
+      base::polymorphic_downcast<SoftwareImageData*>(source_data.release()));
 
   return scoped_refptr<render_tree::Image>(
-      new SkiaSoftwareImage(skia_source_data.Pass()));
+      new SoftwareImage(skia_source_data.Pass()));
 }
 
 scoped_ptr<render_tree::RawImageMemory>
-SkiaSoftwareResourceProvider::AllocateRawImageMemory(size_t size_in_bytes,
-                                                     size_t alignment) {
+SoftwareResourceProvider::AllocateRawImageMemory(size_t size_in_bytes,
+                                                 size_t alignment) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::AllocateRawImageMemory()");
+               "SoftwareResourceProvider::AllocateRawImageMemory()");
 
   return scoped_ptr<render_tree::RawImageMemory>(
-      new SkiaSoftwareRawImageMemory(size_in_bytes, alignment));
+      new SoftwareRawImageMemory(size_in_bytes, alignment));
 }
 
 scoped_refptr<render_tree::Image>
-SkiaSoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory(
+SoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory(
     scoped_ptr<render_tree::RawImageMemory> raw_image_memory,
     const render_tree::MultiPlaneImageDataDescriptor& descriptor) {
   TRACE_EVENT0(
       "cobalt::renderer",
-      "SkiaSoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory()");
+      "SoftwareResourceProvider::CreateMultiPlaneImageFromRawMemory()");
 
-  scoped_ptr<SkiaSoftwareRawImageMemory> skia_software_raw_image_memory(
-      base::polymorphic_downcast<SkiaSoftwareRawImageMemory*>(
+  scoped_ptr<SoftwareRawImageMemory> skia_software_raw_image_memory(
+      base::polymorphic_downcast<SoftwareRawImageMemory*>(
           raw_image_memory.release()));
 
-  return make_scoped_refptr(new SkiaSoftwareMultiPlaneImage(
+  return make_scoped_refptr(new SoftwareMultiPlaneImage(
       skia_software_raw_image_memory.Pass(), descriptor));
 }
 
-bool SkiaSoftwareResourceProvider::HasLocalFontFamily(
+bool SoftwareResourceProvider::HasLocalFontFamily(
     const char* font_family_name) const {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::HasLocalFontFamily()");
+               "SoftwareResourceProvider::HasLocalFontFamily()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkFontStyleSet> style_set(fm->matchFamily(font_family_name));
   return style_set->count() > 0;
 }
 
-scoped_refptr<render_tree::Typeface>
-SkiaSoftwareResourceProvider::GetLocalTypeface(
+scoped_refptr<render_tree::Typeface> SoftwareResourceProvider::GetLocalTypeface(
     const char* font_family_name, render_tree::FontStyle font_style) {
-  TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::GetLocalFont()");
+  TRACE_EVENT0("cobalt::renderer", "SoftwareResourceProvider::GetLocalFont()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkTypeface> typeface(fm->matchFamilyStyle(
@@ -119,11 +115,11 @@
 }
 
 scoped_refptr<render_tree::Typeface>
-SkiaSoftwareResourceProvider::GetCharacterFallbackTypeface(
+SoftwareResourceProvider::GetCharacterFallbackTypeface(
     int32 character, render_tree::FontStyle font_style,
     const std::string& language) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::GetCharacterFallbackTypeface()");
+               "SoftwareResourceProvider::GetCharacterFallbackTypeface()");
 
   SkAutoTUnref<SkFontMgr> fm(SkFontMgr::RefDefault());
   SkAutoTUnref<SkTypeface> typeface(
@@ -133,11 +129,11 @@
 }
 
 scoped_refptr<render_tree::Typeface>
-SkiaSoftwareResourceProvider::CreateTypefaceFromRawData(
+SoftwareResourceProvider::CreateTypefaceFromRawData(
     scoped_ptr<render_tree::ResourceProvider::RawTypefaceDataVector> raw_data,
     std::string* error_string) {
   TRACE_EVENT0("cobalt::renderer",
-               "SkiaSoftwareResourceProvider::CreateFontFromRawData()");
+               "SoftwareResourceProvider::CreateFontFromRawData()");
 
   if (raw_data == NULL) {
     *error_string = "No data to process";
@@ -168,7 +164,7 @@
 }
 
 scoped_refptr<render_tree::GlyphBuffer>
-SkiaSoftwareResourceProvider::CreateGlyphBuffer(
+SoftwareResourceProvider::CreateGlyphBuffer(
     const char16* text_buffer, size_t text_length, const std::string& language,
     bool is_rtl, render_tree::FontProvider* font_provider) {
   return text_shaper_.CreateGlyphBuffer(text_buffer, text_length, language,
@@ -176,13 +172,13 @@
 }
 
 scoped_refptr<render_tree::GlyphBuffer>
-SkiaSoftwareResourceProvider::CreateGlyphBuffer(
+SoftwareResourceProvider::CreateGlyphBuffer(
     const std::string& utf8_string,
     const scoped_refptr<render_tree::Font>& font) {
   return text_shaper_.CreateGlyphBuffer(utf8_string, font);
 }
 
-float SkiaSoftwareResourceProvider::GetTextWidth(
+float SoftwareResourceProvider::GetTextWidth(
     const char16* text_buffer, size_t text_length, const std::string& language,
     bool is_rtl, render_tree::FontProvider* font_provider,
     render_tree::FontVector* maybe_used_fonts) {
diff --git a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
index deb9b79..890f929 100644
--- a/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
+++ b/src/cobalt/renderer/rasterizer/skia/software_resource_provider.h
@@ -29,7 +29,7 @@
 
 // This class must be thread-safe and capable of creating resources that
 // are to be consumed by this skia software rasterizer.
-class SkiaSoftwareResourceProvider : public render_tree::ResourceProvider {
+class SoftwareResourceProvider : public render_tree::ResourceProvider {
  public:
   bool PixelFormatSupported(render_tree::PixelFormat pixel_format) OVERRIDE;
   bool AlphaFormatSupported(render_tree::AlphaFormat alpha_format) OVERRIDE;
diff --git a/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc b/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc
index 0c293a0..447ab7a 100644
--- a/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc
+++ b/src/cobalt/renderer/rasterizer/skia/surface_cache_delegate.cc
@@ -163,11 +163,6 @@
   TRACE_EVENT0("cobalt::renderer", "SurfaceCacheDelegate::EndRecording()");
   DCHECK(recording_data_);
 
-  {
-    TRACE_EVENT0("cobalt::renderer", "SurfaceCacheDelegate canvas_->flush()");
-    canvas_->flush();
-  }
-
   set_canvas_function_.Run(recording_data_->original_canvas);
   canvas_ = recording_data_->original_canvas;
 
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
index b827b56..fab2780 100644
--- a/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
+++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.cc
@@ -71,17 +71,17 @@
 TextShaper::TextShaper()
     : local_glyph_array_size_(0), local_text_buffer_size_(0) {}
 
-scoped_refptr<SkiaGlyphBuffer> TextShaper::CreateGlyphBuffer(
+scoped_refptr<GlyphBuffer> TextShaper::CreateGlyphBuffer(
     const char16* text_buffer, size_t text_length, const std::string& language,
     bool is_rtl, render_tree::FontProvider* font_provider) {
   math::RectF bounds;
   SkTextBlobBuilder builder;
   ShapeText(text_buffer, text_length, language, is_rtl, font_provider, &builder,
             &bounds, NULL);
-  return make_scoped_refptr(new SkiaGlyphBuffer(bounds, &builder));
+  return make_scoped_refptr(new GlyphBuffer(bounds, &builder));
 }
 
-scoped_refptr<SkiaGlyphBuffer> TextShaper::CreateGlyphBuffer(
+scoped_refptr<GlyphBuffer> TextShaper::CreateGlyphBuffer(
     const std::string& utf8_string,
     const scoped_refptr<render_tree::Font>& font) {
   string16 utf16_string;
@@ -174,7 +174,7 @@
   int32 next_character = base::unicode::NormalizeSpaces(
       base::i18n::UTF16CharIterator(text_buffer, text_length).get());
   render_tree::GlyphIndex next_glyph = render_tree::kInvalidGlyphIndex;
-  SkiaFont* next_font = base::polymorphic_downcast<SkiaFont*>(
+  Font* next_font = base::polymorphic_downcast<Font*>(
       font_provider->GetCharacterFont(next_character, &next_glyph).get());
 
   UErrorCode error_code = U_ZERO_ERROR;
@@ -189,7 +189,7 @@
   unsigned int current_index = 0;
   unsigned int end_index = text_length;
   while (current_index < end_index) {
-    SkiaFont* current_font = next_font;
+    Font* current_font = next_font;
     UScriptCode current_script = next_script;
 
     // Create an iterator starting at the current index and containing the
@@ -219,7 +219,7 @@
         continue;
       }
 
-      next_font = base::polymorphic_downcast<SkiaFont*>(
+      next_font = base::polymorphic_downcast<Font*>(
           font_provider->GetCharacterFont(next_character, &next_glyph).get());
 
       next_script = uscript_getScript(next_character, &error_code);
@@ -398,7 +398,7 @@
   }
 
   int glyph_count = 0;
-  SkiaFont* last_font = NULL;
+  Font* last_font = NULL;
 
   // Walk through each character within the run.
   for (base::i18n::UTF16CharIterator iter(text_buffer, text_length);
@@ -422,7 +422,7 @@
     }
 
     // Look up the font and glyph for the current character.
-    SkiaFont* current_font = base::polymorphic_downcast<SkiaFont*>(
+    Font* current_font = base::polymorphic_downcast<Font*>(
         font_provider->GetCharacterFont(character, &glyph).get());
 
     // If there's a builder (meaning that a glyph buffer is being generated),
diff --git a/src/cobalt/renderer/rasterizer/skia/text_shaper.h b/src/cobalt/renderer/rasterizer/skia/text_shaper.h
index 69a936d..a1f6e38 100644
--- a/src/cobalt/renderer/rasterizer/skia/text_shaper.h
+++ b/src/cobalt/renderer/rasterizer/skia/text_shaper.h
@@ -43,16 +43,16 @@
 class TextShaper {
  public:
   // A script run represents a segment of text that can be shaped using a single
-  // SkiaFont and UScriptCode combination.
+  // skia::Font and UScriptCode combination.
   struct ScriptRun {
-    ScriptRun(SkiaFont* run_font, UScriptCode run_script,
+    ScriptRun(Font* run_font, UScriptCode run_script,
               unsigned int run_start_index, unsigned int run_length)
         : font(run_font),
           script(run_script),
           start_index(run_start_index),
           length(run_length) {}
 
-    SkiaFont* font;
+    Font* font;
     UScriptCode script;
     unsigned int start_index;
     unsigned int length;
@@ -69,7 +69,7 @@
   // If |is_rtl| is true, then the glyphs in the text buffer will be reversed.
   // Returns a newly created glyph buffer, which can be used to render the
   // shaped text.
-  scoped_refptr<SkiaGlyphBuffer> CreateGlyphBuffer(
+  scoped_refptr<GlyphBuffer> CreateGlyphBuffer(
       const char16* text_buffer, size_t text_length,
       const std::string& language, bool is_rtl,
       render_tree::FontProvider* font_provider);
@@ -78,7 +78,7 @@
   // complex, depending on the text provided.
   // Returns a newly created glyph buffer, which can be used to render the
   // shaped text.
-  scoped_refptr<SkiaGlyphBuffer> CreateGlyphBuffer(
+  scoped_refptr<GlyphBuffer> CreateGlyphBuffer(
       const std::string& utf8_string,
       const scoped_refptr<render_tree::Font>& font);
 
@@ -117,9 +117,9 @@
     float max_y_;
   };
 
-  // Shape text relying on SkiaFont and HarfBuzz.
+  // Shape text relying on skia::Font and HarfBuzz.
   // Returns the width of the shaped text.
-  // If |maybe_glyph_buffer| is non-NULL, it is populated with SkiaGlyphBuffer
+  // If |maybe_glyph_buffer| is non-NULL, it is populated with skia::GlyphBuffer
   // shaping data.
   // If |maybe_bounds| is non-NULL, it is populated with the bounds of the
   // shaped text.
@@ -132,7 +132,7 @@
                   render_tree::FontVector* maybe_used_fonts);
 
   // Populate a ScriptRuns object with all runs of text containing a single
-  // SkiaFont and UScriptCode combination.
+  // skia::Font and UScriptCode combination.
   // Returns false if the script run collection fails.
   bool CollectScriptRuns(const char16* text_buffer, size_t text_length,
                          render_tree::FontProvider* font_provider,
@@ -157,7 +157,7 @@
                                    render_tree::FontVector* maybe_used_fonts,
                                    float* current_width);
 
-  // Shape a simple text run, relying on the SkiaFont objects provided by
+  // Shape a simple text run, relying on the skia::Font objects provided by
   // the FontProvider to determine the shaping data.
   void ShapeSimpleRun(const char16* text_buffer, size_t text_length,
                       render_tree::FontProvider* font_provider,
diff --git a/src/cobalt/renderer/rasterizer/skia/typeface.cc b/src/cobalt/renderer/rasterizer/skia/typeface.cc
index 5dea364..bb1d64e 100644
--- a/src/cobalt/renderer/rasterizer/skia/typeface.cc
+++ b/src/cobalt/renderer/rasterizer/skia/typeface.cc
@@ -49,7 +49,7 @@
 
 scoped_refptr<render_tree::Font> SkiaTypeface::CreateFontWithSize(
     float font_size) {
-  return scoped_refptr<render_tree::Font>(new SkiaFont(this, font_size));
+  return scoped_refptr<render_tree::Font>(new Font(this, font_size));
 }
 
 render_tree::GlyphIndex SkiaTypeface::GetGlyphForCharacter(
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png
new file mode 100644
index 0000000..3df4cdf
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageSupport-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png
new file mode 100644
index 0000000..43c761e
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithDestSizeDifferentFromImage-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png
new file mode 100644
index 0000000..8f1e33b
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/TwoPlaneYUVImageWithTransform-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png b/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png
new file mode 100644
index 0000000..e7d2f2c
--- /dev/null
+++ b/src/cobalt/renderer/rasterizer/testdata/YUV2PlaneImagesAreLinearlyInterpolated-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/rasterizer/testdata/YUVImagesAreLinearlyInterpolated-expected.png b/src/cobalt/renderer/rasterizer/testdata/YUV3PlaneImagesAreLinearlyInterpolated-expected.png
similarity index 100%
rename from src/cobalt/renderer/rasterizer/testdata/YUVImagesAreLinearlyInterpolated-expected.png
rename to src/cobalt/renderer/rasterizer/testdata/YUV3PlaneImagesAreLinearlyInterpolated-expected.png
Binary files differ
diff --git a/src/cobalt/renderer/render_tree_pixel_tester.cc b/src/cobalt/renderer/render_tree_pixel_tester.cc
index 2ded465..6e6fa75 100644
--- a/src/cobalt/renderer/render_tree_pixel_tester.cc
+++ b/src/cobalt/renderer/render_tree_pixel_tester.cc
@@ -71,7 +71,7 @@
   // Create the rasterizer using the platform default RenderModule options.
   RendererModule::Options render_module_options;
   rasterizer_ = render_module_options.create_rasterizer_function.Run(
-      graphics_context_.get());
+      graphics_context_.get(), render_module_options);
 }
 
 RenderTreePixelTester::~RenderTreePixelTester() {}
diff --git a/src/cobalt/renderer/renderer.gyp b/src/cobalt/renderer/renderer.gyp
index ccc8962..657e39e 100644
--- a/src/cobalt/renderer/renderer.gyp
+++ b/src/cobalt/renderer/renderer.gyp
@@ -37,6 +37,12 @@
         'copy_font_data.gypi',
       ],
 
+      'defines': [
+        'COBALT_SKIA_CACHE_SIZE_IN_BYTES=<(skia_cache_size_in_bytes)',
+        'COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES=<(scratch_surface_cache_size_in_bytes)',
+        'COBALT_SURFACE_CACHE_SIZE_IN_BYTES=<(surface_cache_size_in_bytes)',
+      ],
+
       'dependencies': [
         '<(DEPTH)/cobalt/base/base.gyp:base',
         '<(DEPTH)/cobalt/math/math.gyp:math',
@@ -129,7 +135,7 @@
       'variables': {
         'executable_name': 'renderer_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
@@ -155,7 +161,7 @@
       'variables': {
         'executable_name': 'renderer_benchmark',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/renderer/renderer_module.cc b/src/cobalt/renderer/renderer_module.cc
index c5c96fd..5806add 100644
--- a/src/cobalt/renderer/renderer_module.cc
+++ b/src/cobalt/renderer/renderer_module.cc
@@ -60,7 +60,8 @@
   {
     TRACE_EVENT0("cobalt::renderer", "new renderer::Pipeline()");
     pipeline_ = make_scoped_ptr(new renderer::Pipeline(
-        base::Bind(options.create_rasterizer_function, graphics_context_.get()),
+        base::Bind(options.create_rasterizer_function, graphics_context_.get(),
+                   options),
         display_->GetRenderTarget(), graphics_context_.get()));
   }
 }
diff --git a/src/cobalt/renderer/renderer_module.h b/src/cobalt/renderer/renderer_module.h
index 3f81dc7..f60a29d 100644
--- a/src/cobalt/renderer/renderer_module.h
+++ b/src/cobalt/renderer/renderer_module.h
@@ -34,9 +34,32 @@
     Options();
 
     typedef base::Callback<scoped_ptr<rasterizer::Rasterizer>(
-        backend::GraphicsContext*)> CreateRasterizerCallback;
+        backend::GraphicsContext*, const Options& options)>
+        CreateRasterizerCallback;
+
+    // The rasterizer must be created, accessed, and destroyed within the same
+    // thread, and so to facilitate that a rasterizer factory function must
+    // be provided here instead of the rasterizer itself.
     CreateRasterizerCallback create_rasterizer_function;
 
+    // Determines the capacity of the scratch surface cache.  The scratch
+    // surface cache facilitates the reuse of temporary offscreen surfaces
+    // within a single frame.  This setting is only relevant when using the
+    // hardware-accelerated Skia rasterizer.
+    int scratch_surface_cache_size_in_bytes;
+
+    // Determines the capacity of the skia cache.  The Skia cache is maintained
+    // within Skia and is used to cache the results of complicated effects such
+    // as shadows, so that Skia draw calls that are used repeatedly across
+    // frames can be cached into surfaces.  This setting is only relevant when
+    // using the hardware-accelerated Skia rasterizer.
+    int skia_cache_size_in_bytes;
+
+    // Determines the capacity of the surface cache.  The surface cache tracks
+    // which render tree nodes are being re-used across frames and stores the
+    // nodes that are most CPU-expensive to render into surfaces.
+    int surface_cache_size_in_bytes;
+
    private:
     // Implemented per-platform, and allows each platform to customize
     // the renderer options.
diff --git a/src/cobalt/renderer/renderer_module_default_options_starboard.cc b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
index fdb03b6..50a38f0 100644
--- a/src/cobalt/renderer/renderer_module_default_options_starboard.cc
+++ b/src/cobalt/renderer/renderer_module_default_options_starboard.cc
@@ -26,31 +26,34 @@
 namespace renderer {
 
 namespace {
+
 scoped_ptr<rasterizer::Rasterizer> CreateRasterizer(
-    backend::GraphicsContext* graphics_context) {
-  const size_t kSurfaceCacheCapacityInBytes = 0;
+    backend::GraphicsContext* graphics_context,
+    const RendererModule::Options& options) {
 #if COBALT_FORCE_STUB_RASTERIZER
   return scoped_ptr<rasterizer::Rasterizer>(new rasterizer::stub::Rasterizer());
 #else
 #if SB_HAS(GLES2)
 #if COBALT_FORCE_SOFTWARE_RASTERIZER
   return scoped_ptr<rasterizer::Rasterizer>(
-      new rasterizer::egl::SoftwareRasterizer(graphics_context,
-                                              kSurfaceCacheCapacityInBytes));
+      new rasterizer::egl::SoftwareRasterizer(
+          graphics_context, options.surface_cache_size_in_bytes));
 #else
   return scoped_ptr<rasterizer::Rasterizer>(
-      new rasterizer::skia::SkiaHardwareRasterizer(
-          graphics_context, kSurfaceCacheCapacityInBytes));
+      new rasterizer::skia::HardwareRasterizer(
+          graphics_context, options.skia_cache_size_in_bytes,
+          options.scratch_surface_cache_size_in_bytes,
+          options.surface_cache_size_in_bytes));
 #endif  // COBALT_FORCE_SOFTWARE_RASTERIZER
 #elif SB_HAS(BLITTER)
 #if COBALT_FORCE_SOFTWARE_RASTERIZER
   return scoped_ptr<rasterizer::Rasterizer>(
       new rasterizer::blitter::SoftwareRasterizer(
-          graphics_context, kSurfaceCacheCapacityInBytes));
+          graphics_context, options.surface_cache_size_in_bytes));
 #else
   return scoped_ptr<rasterizer::Rasterizer>(
       new rasterizer::blitter::HardwareRasterizer(
-          graphics_context, kSurfaceCacheCapacityInBytes));
+          graphics_context, options.surface_cache_size_in_bytes));
 #endif  // COBALT_FORCE_SOFTWARE_RASTERIZER
 #else
 #error "Either GLES2 or the Starboard Blitter API must be available."
@@ -61,6 +64,12 @@
 }  // namespace
 
 void RendererModule::Options::SetPerPlatformDefaultOptions() {
+  // Set default options from the current build's Starboard configuration.
+  surface_cache_size_in_bytes = COBALT_SURFACE_CACHE_SIZE_IN_BYTES;
+  skia_cache_size_in_bytes = COBALT_SKIA_CACHE_SIZE_IN_BYTES;
+  scratch_surface_cache_size_in_bytes =
+      COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES;
+
   create_rasterizer_function = base::Bind(&CreateRasterizer);
 }
 
diff --git a/src/cobalt/renderer/renderer_module_default_options_win.cc b/src/cobalt/renderer/renderer_module_default_options_win.cc
index 2cf8fe3..6b08fc9 100644
--- a/src/cobalt/renderer/renderer_module_default_options_win.cc
+++ b/src/cobalt/renderer/renderer_module_default_options_win.cc
@@ -24,21 +24,29 @@
 
 namespace {
 scoped_ptr<rasterizer::Rasterizer> CreateRasterizer(
-    backend::GraphicsContext* graphics_context) {
-  const size_t kSurfaceCacheCapacityInBytes = 0;
+    backend::GraphicsContext* graphics_context,
+    const RendererModule::Options& options) {
 #if COBALT_FORCE_SOFTWARE_RASTERIZER
   return scoped_ptr<rasterizer::Rasterizer>(
-      new rasterizer::egl::SoftwareRasterizer(graphics_context,
-                                              kSurfaceCacheCapacityInBytes));
+      new rasterizer::egl::SoftwareRasterizer(
+          graphics_context, options.surface_cache_size_in_bytes));
 #else
   return scoped_ptr<rasterizer::Rasterizer>(
-      new rasterizer::skia::SkiaHardwareRasterizer(
-          graphics_context, kSurfaceCacheCapacityInBytes));
+      new rasterizer::skia::HardwareRasterizer(
+          graphics_context, options.skia_cache_size_in_bytes,
+          options.scratch_surface_cache_size_in_bytes,
+          options.surface_cache_size_in_bytes));
 #endif  // #if COBALT_FORCE_SOFTWARE_RASTERIZER
 }
 }  // namespace
 
 void RendererModule::Options::SetPerPlatformDefaultOptions() {
+  // Set default options from the current build's configuration.
+  surface_cache_size_in_bytes = COBALT_SURFACE_CACHE_SIZE_IN_BYTES;
+  skia_cache_size_in_bytes = COBALT_SKIA_CACHE_SIZE_IN_BYTES;
+  scratch_surface_cache_size_in_bytes =
+      COBALT_SCRATCH_SURFACE_CACHE_SIZE_IN_BYTES;
+
   create_rasterizer_function = base::Bind(&CreateRasterizer);
 }
 
diff --git a/src/cobalt/renderer/resource_provider_test.cc b/src/cobalt/renderer/resource_provider_test.cc
index 33ff33c..e511354 100644
--- a/src/cobalt/renderer/resource_provider_test.cc
+++ b/src/cobalt/renderer/resource_provider_test.cc
@@ -155,7 +155,7 @@
   RendererModule::Options render_module_options;
   scoped_ptr<rasterizer::Rasterizer> rasterizer =
       render_module_options.create_rasterizer_function.Run(
-          graphics_context.get());
+          graphics_context.get(), render_module_options);
 
   // Create a dummy offscreen surface so that we can have a target when we start
   // a frame with the graphics context.
@@ -208,7 +208,7 @@
   RendererModule::Options render_module_options;
   scoped_ptr<rasterizer::Rasterizer> rasterizer =
       render_module_options.create_rasterizer_function.Run(
-          graphics_context.get());
+          graphics_context.get(), render_module_options);
 
   // Create a dummy offscreen surface so that we can have a target when we start
   // a frame with the graphics context.
diff --git a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc
index 18606d4..dc54939 100644
--- a/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc
+++ b/src/cobalt/renderer/sandbox/renderer_sandbox_main.cc
@@ -38,46 +38,65 @@
 const int kViewportWidth = 1920;
 const int kViewportHeight = 1080;
 
-int SandboxMain(int argc, char** argv) {
-  MessageLoop message_loop(MessageLoop::TYPE_DEFAULT);
+class RendererSandbox {
+ public:
+  RendererSandbox();
 
-  cobalt::trace_event::ScopedTraceToFile trace_to_file(
-      FilePath(FILE_PATH_LITERAL("renderer_sandbox_trace.json")));
+ private:
+  cobalt::trace_event::ScopedTraceToFile trace_to_file_;
+  base::EventDispatcher event_dispatcher_;
+  scoped_ptr<SystemWindow> system_window_;
+  scoped_ptr<cobalt::renderer::RendererModule> renderer_module_;
+};
 
-  base::EventDispatcher event_dispatcher;
+RendererSandbox::RendererSandbox()
+    : trace_to_file_(
+          FilePath(FILE_PATH_LITERAL("renderer_sandbox_trace.json"))) {
   // Create a system window to use as a render target.
-  scoped_ptr<SystemWindow> system_window =
-      cobalt::system_window::CreateSystemWindow(
-          &event_dispatcher,
-          cobalt::math::Size(kViewportWidth, kViewportHeight));
+  system_window_ = cobalt::system_window::CreateSystemWindow(
+      &event_dispatcher_, cobalt::math::Size(kViewportWidth, kViewportHeight));
 
   // Construct a renderer module using default options.
   cobalt::renderer::RendererModule::Options renderer_module_options;
-  cobalt::renderer::RendererModule renderer_module(system_window.get(),
-                                                   renderer_module_options);
+  renderer_module_.reset(new cobalt::renderer::RendererModule(
+      system_window_.get(), renderer_module_options));
 
   cobalt::math::SizeF output_dimensions(
-      renderer_module.render_target()->GetSize());
+      renderer_module_->render_target()->GetSize());
 
   // Construct our render tree and associated animations to be passed into
   // the renderer pipeline for display.
   base::TimeDelta start_time = base::Time::Now() - base::Time::UnixEpoch();
   RenderTreeWithAnimations scene = AddBlankBackgroundToScene(
       CreateAllScenesCombinedScene(
-          renderer_module.pipeline()->GetResourceProvider(), output_dimensions,
-          start_time),
+          renderer_module_->pipeline()->GetResourceProvider(),
+          output_dimensions, start_time),
       output_dimensions);
 
   // Pass the render tree along with associated animations into the renderer
   // module to be displayed.
-  renderer_module.pipeline()->Submit(cobalt::renderer::Submission(
+  renderer_module_->pipeline()->Submit(cobalt::renderer::Submission(
       scene.render_tree, scene.animations, start_time));
+}
 
-  base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(30));
+RendererSandbox* g_renderer_sandbox = NULL;
 
-  return 0;
+void StartApplication(int /*argc*/, char** /*argv*/,
+                      const base::Closure& quit_closure) {
+  DCHECK(!g_renderer_sandbox);
+  g_renderer_sandbox = new RendererSandbox();
+  DCHECK(g_renderer_sandbox);
+
+  MessageLoop::current()->PostDelayedTask(FROM_HERE, quit_closure,
+                                          base::TimeDelta::FromSeconds(30));
+}
+
+void StopApplication() {
+  DCHECK(g_renderer_sandbox);
+  delete g_renderer_sandbox;
+  g_renderer_sandbox = NULL;
 }
 
 }  // namespace
 
-COBALT_WRAP_SIMPLE_MAIN(SandboxMain);
+COBALT_WRAP_BASE_MAIN(StartApplication, StopApplication);
diff --git a/src/cobalt/renderer/sandbox/sandbox.gyp b/src/cobalt/renderer/sandbox/sandbox.gyp
index e16ee63..7cf08e7 100644
--- a/src/cobalt/renderer/sandbox/sandbox.gyp
+++ b/src/cobalt/renderer/sandbox/sandbox.gyp
@@ -45,7 +45,7 @@
       'variables': {
         'executable_name': 'renderer_sandbox',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
 
     {
@@ -76,7 +76,7 @@
       'variables': {
         'executable_name': 'scaling_text_sandbox',
       },
-      'includes': [ '../../build/deploy.gypi' ],
+      'includes': [ '../../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/renderer/test/png_utils/png_decode.cc b/src/cobalt/renderer/test/png_utils/png_decode.cc
index d582eee..4bf217b 100644
--- a/src/cobalt/renderer/test/png_utils/png_decode.cc
+++ b/src/cobalt/renderer/test/png_utils/png_decode.cc
@@ -184,6 +184,7 @@
         case render_tree::kPixelFormatY8:
         case render_tree::kPixelFormatU8:
         case render_tree::kPixelFormatV8:
+        case render_tree::kPixelFormatUV8:
         case render_tree::kPixelFormatInvalid: {
           NOTREACHED();
         }
@@ -202,6 +203,7 @@
         case render_tree::kPixelFormatY8:
         case render_tree::kPixelFormatU8:
         case render_tree::kPixelFormatV8:
+        case render_tree::kPixelFormatUV8:
         case render_tree::kPixelFormatInvalid: {
           NOTREACHED();
         }
diff --git a/src/cobalt/samples/samples.gyp b/src/cobalt/samples/samples.gyp
index 7928dde..df34d7d 100644
--- a/src/cobalt/samples/samples.gyp
+++ b/src/cobalt/samples/samples.gyp
@@ -76,7 +76,7 @@
       'variables': {
         'executable_name': 'simple_example',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     # This target will create a test for simple_example.
@@ -123,7 +123,7 @@
       'variables': {
         'executable_name': 'simple_example_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/script/javascriptcore/conversion_helpers.h b/src/cobalt/script/javascriptcore/conversion_helpers.h
index 6d345b0..4642fc9 100644
--- a/src/cobalt/script/javascriptcore/conversion_helpers.h
+++ b/src/cobalt/script/javascriptcore/conversion_helpers.h
@@ -349,6 +349,32 @@
   *out_number = static_cast<T>(uint32_value);
 }
 
+// JSValue -> signed integers > 4 bytes
+template <class T>
+inline void FromJSValue(
+    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
+    ExceptionState* out_exception, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
+// JSValue -> unsigned integers > 4 bytes
+template <class T>
+inline void FromJSValue(
+    JSC::ExecState* exec_state, JSC::JSValue jsvalue, int conversion_flags,
+    ExceptionState* out_exception, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  NOTIMPLEMENTED();
+}
+
 // JSValue -> double
 template <class T>
 inline void FromJSValue(
diff --git a/src/cobalt/script/javascriptcore/javascriptcore.gyp b/src/cobalt/script/javascriptcore/javascriptcore.gyp
index 8dce193..0504492 100644
--- a/src/cobalt/script/javascriptcore/javascriptcore.gyp
+++ b/src/cobalt/script/javascriptcore/javascriptcore.gyp
@@ -67,6 +67,11 @@
         '<(DEPTH)/cobalt/script/script.gyp:script',
         '<(DEPTH)/third_party/WebKit/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp:javascriptcore',
       ],
+      'all_dependent_settings': {
+        'defines': [
+          'ENGINE_DEFINES_ATTRIBUTES_ON_OBJECT',
+        ],
+      },
       'msvs_disabled_warnings': [
         # dll-interface warnings. Not easily fixed for template types.
         4251,
diff --git a/src/cobalt/script/javascriptcore/jsc_call_frame.cc b/src/cobalt/script/javascriptcore/jsc_call_frame.cc
index 3fe27ba..864e8d0 100644
--- a/src/cobalt/script/javascriptcore/jsc_call_frame.cc
+++ b/src/cobalt/script/javascriptcore/jsc_call_frame.cc
@@ -107,7 +107,7 @@
 }
 
 std::string JSCCallFrame::GetFunctionName() {
-  return call_frame_.functionName().latin1().data();
+  return call_frame_.functionName().utf8().data();
 }
 
 int JSCCallFrame::GetLineNumber() {
diff --git a/src/cobalt/script/javascriptcore/jsc_debugger.cc b/src/cobalt/script/javascriptcore/jsc_debugger.cc
index 8508430..9856564 100644
--- a/src/cobalt/script/javascriptcore/jsc_debugger.cc
+++ b/src/cobalt/script/javascriptcore/jsc_debugger.cc
@@ -225,7 +225,7 @@
     // Script failed to parse.
     delegate_->OnScriptFailedToParse(
         scoped_ptr<SourceProvider>(new JSCSourceProvider(
-            source_provider, error_line, error_message.latin1().data())));
+            source_provider, error_line, error_message.utf8().data())));
   }
 }
 
diff --git a/src/cobalt/script/javascriptcore/jsc_source_provider.cc b/src/cobalt/script/javascriptcore/jsc_source_provider.cc
index 1356bf5..836b044 100644
--- a/src/cobalt/script/javascriptcore/jsc_source_provider.cc
+++ b/src/cobalt/script/javascriptcore/jsc_source_provider.cc
@@ -81,7 +81,7 @@
 }
 
 std::string JSCSourceProvider::GetScriptSource() {
-  return source_provider_->source().latin1().data();
+  return source_provider_->source().utf8().data();
 }
 
 base::optional<std::string> JSCSourceProvider::GetSourceMapUrl() {
@@ -98,7 +98,7 @@
 }
 
 std::string JSCSourceProvider::GetUrl() {
-  return source_provider_->url().latin1().data();
+  return source_provider_->url().utf8().data();
 }
 
 base::optional<bool> JSCSourceProvider::IsContentScript() {
diff --git a/src/cobalt/script/mozjs/callback_function_conversion.h b/src/cobalt/script/mozjs/callback_function_conversion.h
new file mode 100644
index 0000000..1e0966d
--- /dev/null
+++ b/src/cobalt/script/mozjs/callback_function_conversion.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_
+#define COBALT_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_
+
+#include "base/logging.h"
+#include "cobalt/base/polymorphic_downcast.h"
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/mozjs_callback_function.h"
+#include "cobalt/script/script_object.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// CallbackFunction -> JSValue
+template <typename Signature>
+void ToJSValue(
+    JSContext* context,
+    const ScriptObject<CallbackFunction<Signature> >* callback_function,
+    JS::MutableHandleValue out_value) {
+  if (!callback_function) {
+    out_value.set(JS::NullValue());
+    return;
+  }
+  // Downcast to MozjsUserObjectHolder<T> so we can get the underlying JSObject.
+  typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> >
+      MozjsUserObjectHolderClass;
+  const MozjsUserObjectHolderClass* user_object_holder =
+      base::polymorphic_downcast<const MozjsUserObjectHolderClass*>(
+          callback_function);
+
+  DCHECK(user_object_holder->js_object());
+  out_value.set(OBJECT_TO_JSVAL(user_object_holder->js_object()));
+}
+
+// JSValue -> CallbackFunction
+template <typename Signature>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 MozjsUserObjectHolder<MozjsCallbackFunction<Signature> >*
+                     out_callback_function) {
+  typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> >
+      MozjsCallbackHolderClass;
+
+  DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0)
+      << "Unexpected conversion flags.";
+
+  if (value.isNull()) {
+    if (!(conversion_flags & kConversionFlagNullable)) {
+      exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                          kNotNullableType);
+    }
+    // If it is a nullable type, just return.
+    return;
+  }
+
+  // https://www.w3.org/TR/WebIDL/#es-callback-function
+  // 1. If V is not a Function object, throw a TypeError
+  JS::RootedObject object(context);
+  if (value.isObject()) {
+    object = JSVAL_TO_OBJECT(value);
+  }
+  if (!object || !JS_ObjectIsFunction(context, object)) {
+    exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                        "Value is not a function.");
+    return;
+  }
+
+  MozjsGlobalObjectProxy* global_object_proxy =
+      static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+  *out_callback_function = MozjsCallbackHolderClass(
+      object, context, global_object_proxy->wrapper_factory());
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_CALLBACK_FUNCTION_CONVERSION_H_
diff --git a/src/cobalt/script/mozjs/conversion_helpers.cc b/src/cobalt/script/mozjs/conversion_helpers.cc
index 0da571d..c469d26 100644
--- a/src/cobalt/script/mozjs/conversion_helpers.cc
+++ b/src/cobalt/script/mozjs/conversion_helpers.cc
@@ -24,7 +24,7 @@
 
 // JSValue -> std::string
 void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, MozjsExceptionState* exception_state,
+                 int conversion_flags, ExceptionState* exception_state,
                  std::string* out_string) {
   DCHECK_EQ(conversion_flags & ~kConversionFlagsString, 0)
       << "Unexpected conversion flags found: ";
@@ -41,20 +41,27 @@
     return;
   }
 
-  JSString* string = JS_ValueToString(context, value);
+  JS::RootedString string(context, JS_ValueToString(context, value));
   if (!string) {
     exception_state->SetSimpleException(ExceptionState::kTypeError,
                                         "Not supported type.");
     return;
   }
 
-  *out_string = std::string(JS_EncodeStringToUTF8(context, string));
+  JSAutoByteString auto_byte_string;
+  char* utf8_chars = auto_byte_string.encodeUtf8(context, string);
+  if (!utf8_chars) {
+    exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                        "Failed to convert to utf8.");
+    return;
+  }
+
+  *out_string = utf8_chars;
 }
 
 // OpaqueHandle -> JSValue
 void ToJSValue(JSContext* context,
                const OpaqueHandleHolder* opaque_handle_holder,
-               MozjsExceptionState* exception_state,
                JS::MutableHandleValue out_value) {
   JS::RootedObject js_object(context);
   if (opaque_handle_holder) {
@@ -70,8 +77,8 @@
 
 // JSValue -> OpaqueHandle
 void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, MozjsExceptionState* exception_state,
-                 MozjsObjectHandle::HolderType* out_holder) {
+                 int conversion_flags, ExceptionState* exception_state,
+                 MozjsObjectHandleHolder* out_holder) {
   DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
       << "Unexpected conversion flags found.";
   JS::RootedObject js_object(context);
@@ -98,8 +105,8 @@
   DCHECK(js_object);
   MozjsGlobalObjectProxy* global_object_proxy =
       static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  *out_holder = MozjsObjectHandle::HolderType(
-      js_object, context, global_object_proxy->wrapper_factory());
+  *out_holder = MozjsObjectHandleHolder(js_object, context,
+                                        global_object_proxy->wrapper_factory());
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs/conversion_helpers.h b/src/cobalt/script/mozjs/conversion_helpers.h
index defe56f..cf0206e 100644
--- a/src/cobalt/script/mozjs/conversion_helpers.h
+++ b/src/cobalt/script/mozjs/conversion_helpers.h
@@ -22,12 +22,18 @@
 
 #include "base/logging.h"
 #include "base/optional.h"
+#include "base/stringprintf.h"
 #include "cobalt/base/enable_if.h"
+#include "cobalt/base/token.h"
+#include "cobalt/script/mozjs/mozjs_callback_interface_holder.h"
 #include "cobalt/script/mozjs/mozjs_exception_state.h"
 #include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
 #include "cobalt/script/mozjs/mozjs_object_handle.h"
 #include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/mozjs/union_type_conversion_forward.h"
 #include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jsproxy.h"
 
 namespace cobalt {
 namespace script {
@@ -55,19 +61,43 @@
 
   // Valid conversion flags for objects.
   kConversionFlagsObject = kConversionFlagNullable,
+
+  // Valid conversion flags for callback functions.
+  kConversionFlagsCallbackFunction = kConversionFlagNullable,
+
+  // Valid conversion flags for callback interfaces.
+  kConversionFlagsCallbackInterface = kConversionFlagNullable,
 };
 
+// std::string -> JSValue
+inline void ToJSValue(JSContext* context, const std::string& in_string,
+                      JS::MutableHandleValue out_value) {
+  JS::RootedString rooted_string(
+      context,
+      JS_NewStringCopyN(context, in_string.c_str(), in_string.length()));
+  out_value.set(JS::StringValue(rooted_string));
+}
+
+// JSValue -> std::string
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 std::string* out_string);
+
+// base::Token -> JSValue
+inline void ToJSValue(JSContext* context, const base::Token& token,
+                      JS::MutableHandleValue out_value) {
+  ToJSValue(context, std::string(token.c_str()), out_value);
+}
+
 // bool -> JSValue
 inline void ToJSValue(JSContext* context, bool in_boolean,
-                      MozjsExceptionState* exception_state,
                       JS::MutableHandleValue out_value) {
   out_value.set(JS::BooleanValue(in_boolean));
 }
 
 // JSValue -> bool
 inline void FromJSValue(JSContext* context, JS::HandleValue value,
-                        int conversion_flags,
-                        MozjsExceptionState* exception_state,
+                        int conversion_flags, ExceptionState* exception_state,
                         bool* out_boolean) {
   DCHECK_EQ(conversion_flags, kNoConversionFlags)
       << "No conversion flags supported.";
@@ -79,8 +109,7 @@
 // signed integers <= 4 bytes -> JSValue
 template <typename T>
 inline void ToJSValue(
-    JSContext* context, T in_number, MozjsExceptionState* exception_state,
-    JS::MutableHandleValue out_value,
+    JSContext* context, T in_number, JS::MutableHandleValue out_value,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  std::numeric_limits<T>::is_integer &&
                                  std::numeric_limits<T>::is_signed &&
@@ -93,7 +122,7 @@
 template <typename T>
 inline void FromJSValue(
     JSContext* context, JS::HandleValue value, int conversion_flags,
-    MozjsExceptionState* exception_state, T* out_number,
+    ExceptionState* exception_state, T* out_number,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  std::numeric_limits<T>::is_integer &&
                                  std::numeric_limits<T>::is_signed &&
@@ -112,11 +141,53 @@
   *out_number = static_cast<T>(out);
 }
 
+// JSValue -> signed integers > 4 bytes
+template <typename T>
+inline void FromJSValue(
+    JSContext* context, JS::HandleValue value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  double to_number;
+  JS::ToNumber(context, value, &to_number);
+
+  std::string value_str;
+  FromJSValue(context, value, conversion_flags, exception_state, &value_str);
+  DCHECK_EQ(conversion_flags, kNoConversionFlags)
+      << "No conversion flags supported.";
+  DCHECK(out_number);
+  int64_t out;
+  // This produces an IDL long long.
+  JSBool success = JS_ValueToInt64(context, value, &out);
+  DCHECK(success);
+  if (!success) {
+    exception_state->SetSimpleException(
+        ExceptionState::kTypeError,
+        "Cannot convert a JavaScript value to int64_t.");
+    return;
+  }
+  *out_number = static_cast<T>(out);
+}
+
+// signed integers > 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    JSContext* context, T in_number, JS::MutableHandleValue out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  out_value.set(JS_NumberValue(in_number));
+}
+
 // unsigned integers <= 4 bytes -> JSValue
 template <typename T>
 inline void ToJSValue(
-    JSContext* context, T in_number, MozjsExceptionState* exception_state,
-    JS::MutableHandleValue out_value,
+    JSContext* context, T in_number, JS::MutableHandleValue out_value,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  std::numeric_limits<T>::is_integer &&
                                  !std::numeric_limits<T>::is_signed &&
@@ -129,7 +200,7 @@
 template <typename T>
 inline void FromJSValue(
     JSContext* context, JS::HandleValue value, int conversion_flags,
-    MozjsExceptionState* exception_state, T* out_number,
+    ExceptionState* exception_state, T* out_number,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  std::numeric_limits<T>::is_integer &&
                                  !std::numeric_limits<T>::is_signed &&
@@ -148,11 +219,49 @@
   *out_number = static_cast<T>(out);
 }
 
+// JSValue -> unsigned integers > 4 bytes
+template <typename T>
+inline void FromJSValue(
+    JSContext* context, JS::HandleValue value, int conversion_flags,
+    ExceptionState* exception_state, T* out_number,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  DCHECK_EQ(conversion_flags, kNoConversionFlags)
+      << "No conversion flags supported.";
+  DCHECK(out_number);
+
+  uint64_t out;
+  // This produces and IDL unsigned long long.
+  JSBool success = JS_ValueToUint64(context, value, &out);
+  DCHECK(success);
+  if (!success) {
+    exception_state->SetSimpleException(
+        ExceptionState::kTypeError,
+        "Cannot convert a JavaScript value to uint64_t.");
+    return;
+  }
+  *out_number = static_cast<T>(out);
+}
+
+// unsigned integers > 4 bytes -> JSValue
+template <typename T>
+inline void ToJSValue(
+    JSContext* context, T in_number, JS::MutableHandleValue out_value,
+    typename base::enable_if<std::numeric_limits<T>::is_specialized &&
+                                 std::numeric_limits<T>::is_integer &&
+                                 !std::numeric_limits<T>::is_signed &&
+                                 (sizeof(T) > 4),
+                             T>::type* = NULL) {
+  out_value.set(JS_NumberValue(in_number));
+}
+
 // double -> JSValue
 template <typename T>
 inline void ToJSValue(
-    JSContext* context, T in_number, MozjsExceptionState* exception_state,
-    JS::MutableHandleValue out_value,
+    JSContext* context, T in_number, JS::MutableHandleValue out_value,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  !std::numeric_limits<T>::is_integer,
                              T>::type* = NULL) {
@@ -163,7 +272,7 @@
 template <typename T>
 inline void FromJSValue(
     JSContext* context, JS::HandleValue value, int conversion_flags,
-    MozjsExceptionState* exception_state, T* out_number,
+    ExceptionState* exception_state, T* out_number,
     typename base::enable_if<std::numeric_limits<T>::is_specialized &&
                                  !std::numeric_limits<T>::is_integer,
                              T>::type* = NULL) {
@@ -188,31 +297,21 @@
   *out_number = double_value;
 }
 
-// std::string -> JSValue
-inline void ToJSValue(JSContext* context, const std::string& in_string,
-                      MozjsExceptionState* exception_state,
-                      JS::MutableHandleValue out_value) {
-  out_value.set(JS::StringValue(
-      JS_NewStringCopyN(context, in_string.c_str(), in_string.length())));
-}
-
 // optional<T> -> JSValue
 template <typename T>
 inline void ToJSValue(JSContext* context, const base::optional<T>& in_optional,
-                      MozjsExceptionState* exception_state,
                       JS::MutableHandleValue out_value) {
   if (!in_optional) {
     out_value.setNull();
     return;
   }
-  ToJSValue(context, in_optional.value(), exception_state, out_value);
+  ToJSValue(context, in_optional.value(), out_value);
 }
 
 // JSValue -> optional<T>
 template <typename T>
 inline void FromJSValue(JSContext* context, JS::HandleValue value,
-                        int conversion_flags,
-                        MozjsExceptionState* exception_state,
+                        int conversion_flags, ExceptionState* exception_state,
                         base::optional<T>* out_optional) {
   if (value.isNull()) {
     *out_optional = base::nullopt;
@@ -225,16 +324,10 @@
   }
 }
 
-// JSValue -> std::string
-void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, MozjsExceptionState* exception_state,
-                 std::string* out_string);
-
-// JSValue -> optional<T>
+// JSValue -> optional<std::string>
 template <>
 inline void FromJSValue(JSContext* context, JS::HandleValue value,
-                        int conversion_flags,
-                        MozjsExceptionState* exception_state,
+                        int conversion_flags, ExceptionState* exception_state,
                         base::optional<std::string>* out_optional) {
   if (value.isNull()) {
     *out_optional = base::nullopt;
@@ -253,18 +346,16 @@
 // OpaqueHandle -> JSValue
 void ToJSValue(JSContext* context,
                const OpaqueHandleHolder* opaque_handle_holder,
-               MozjsExceptionState* exception_state,
                JS::MutableHandleValue out_value);
 
 // JSValue -> OpaqueHandle
 void FromJSValue(JSContext* context, JS::HandleValue value,
-                 int conversion_flags, MozjsExceptionState* exception_state,
-                 MozjsObjectHandle::HolderType* out_holder);
+                 int conversion_flags, ExceptionState* exception_state,
+                 MozjsObjectHandleHolder* out_holder);
 
 // object -> JSValue
-template <class T>
+template <typename T>
 inline void ToJSValue(JSContext* context, const scoped_refptr<T>& in_object,
-                      MozjsExceptionState* exception_state,
                       JS::MutableHandleValue out_value) {
   if (!in_object) {
     out_value.setNull();
@@ -274,68 +365,132 @@
   MozjsGlobalObjectProxy* global_object_proxy =
       static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
   JS::RootedObject object(
-      context, global_object_proxy->wrapper_factory()->GetWrapper(in_object));
+      context,
+      global_object_proxy->wrapper_factory()->GetWrapperProxy(in_object));
   DCHECK(object);
 
   out_value.set(OBJECT_TO_JSVAL(object));
 }
 
 // JSValue -> object
-template <class T>
+template <typename T>
 inline void FromJSValue(JSContext* context, JS::HandleValue value,
-                        int conversion_flags,
-                        MozjsExceptionState* exception_state,
+                        int conversion_flags, ExceptionState* exception_state,
                         scoped_refptr<T>* out_object) {
   DCHECK_EQ(conversion_flags & ~kConversionFlagsObject, 0)
       << "Unexpected conversion flags found.";
-
   JS::RootedObject js_object(context);
-  if (value.isNull() && !(conversion_flags & kConversionFlagNullable)) {
-    exception_state->SetSimpleException(ExceptionState::kTypeError,
-                                        kNotNullableType);
+  if (value.isNull()) {
+    if (!(conversion_flags & kConversionFlagNullable)) {
+      exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                          kNotNullableType);
+    }
     return;
   }
-
   if (!JS_ValueToObject(context, value, js_object.address())) {
     exception_state->SetSimpleException(
         ExceptionState::kTypeError,
         "Cannot convert a JavaScript value to an object.");
     return;
   }
-
   DCHECK(js_object);
+  if (js::IsProxy(js_object)) {
+    JS::RootedObject wrapper(context, js::GetProxyTargetObject(js_object));
+    MozjsGlobalObjectProxy* global_object_proxy =
+        static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+    const WrapperFactory* wrapper_factory =
+        global_object_proxy->wrapper_factory();
+    if (wrapper_factory->IsWrapper(wrapper)) {
+      bool object_implements_interface =
+          wrapper_factory->DoesObjectImplementInterface(js_object,
+                                                        base::GetTypeId<T>());
+      if (!object_implements_interface) {
+        exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                            kDoesNotImplementInterface);
+        return;
+      }
+      WrapperPrivate* wrapper_private =
+          WrapperPrivate::GetFromWrapperObject(wrapper);
+      *out_object = wrapper_private->wrappable<T>();
+      return;
+    }
+  }
+  // This is not a platform object. Return a type error.
+  exception_state->SetSimpleException(ExceptionState::kTypeError,
+                                      kDoesNotImplementInterface);
+}
+
+// CallbackInterface -> JSValue
+template <typename T>
+inline void ToJSValue(JSContext* context,
+                      const ScriptObject<T>* callback_interface,
+                      JS::MutableHandleValue out_value) {
+  if (!callback_interface) {
+    out_value.set(JS::NullValue());
+    return;
+  }
+  typedef typename CallbackInterfaceTraits<T>::MozjsCallbackInterfaceClass
+      MozjsCallbackInterfaceClass;
+  // Downcast to MozjsUserObjectHolder<T> so we can get the underlying JSObject.
+  typedef MozjsUserObjectHolder<MozjsCallbackInterfaceClass>
+      MozjsUserObjectHolderClass;
+  const MozjsUserObjectHolderClass* user_object_holder =
+      base::polymorphic_downcast<const MozjsUserObjectHolderClass*>(
+          callback_interface);
+
+  // Shouldn't be NULL. If the callback was NULL then NULL should have been
+  // passed as an argument into this function.
+  // Downcast to the corresponding MozjsCallbackInterface type, from which we
+  // can get the implementing object.
+  const MozjsCallbackInterfaceClass* mozjs_callback_interface =
+      base::polymorphic_downcast<const MozjsCallbackInterfaceClass*>(
+          user_object_holder->GetScriptObject());
+  DCHECK(mozjs_callback_interface);
+  out_value.set(OBJECT_TO_JSVAL(mozjs_callback_interface->handle()));
+}
+
+// JSValue -> CallbackInterface
+template <typename T>
+inline void FromJSValue(
+    JSContext* context, JS::HandleValue value, int conversion_flags,
+    ExceptionState* out_exception,
+    MozjsCallbackInterfaceHolder<T>* out_callback_interface) {
+  typedef T MozjsCallbackInterfaceClass;
+  DCHECK_EQ(conversion_flags & ~kConversionFlagsCallbackFunction, 0)
+      << "No conversion flags supported.";
+  if (value.isNull()) {
+    if (!(conversion_flags & kConversionFlagNullable)) {
+      out_exception->SetSimpleException(ExceptionState::kTypeError,
+                                        kNotNullableType);
+    }
+    // If it is a nullable type, just return.
+    return;
+  }
+
+  // https://www.w3.org/TR/WebIDL/#es-user-objects
+  // Any user object can be considered to implement a user interface. Actually
+  // checking if the correct properties exist will happen when the operation
+  // on the callback interface is run.
+  if (!value.isObject()) {
+    out_exception->SetSimpleException(ExceptionState::kTypeError,
+                                      kNotObjectType);
+    return;
+  }
+
   MozjsGlobalObjectProxy* global_object_proxy =
       static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
-  if (global_object_proxy->wrapper_factory()->IsWrapper(js_object)) {
-    *out_object = WrapperPrivate::GetWrappable<T>(js_object);
-  } else {
-    // This is not a platform object. Return a type error.
-    exception_state->SetSimpleException(ExceptionState::kTypeError,
-                                        kDoesNotImplementInterface);
-  }
-}
 
-// TODO: These will be removed once conversion for all types is implemented.
-template <typename T>
-void ToJSValue(
-    JSContext* context, const T& unimplemented,
-    MozjsExceptionState* exception_state, JS::MutableHandleValue out_value,
-    typename base::enable_if<!std::numeric_limits<T>::is_specialized>::type* =
-        NULL) {
-  NOTIMPLEMENTED();
-}
-
-template <typename T>
-void FromJSValue(
-    JSContext* context, JS::HandleValue value, int conversion_flags,
-    MozjsExceptionState* exception_state, T* out_unimplemented,
-    typename base::enable_if<!std::numeric_limits<T>::is_specialized>::type* =
-        NULL) {
-  NOTIMPLEMENTED();
+  JS::RootedObject implementing_object(context, JSVAL_TO_OBJECT(value));
+  DCHECK(implementing_object);
+  *out_callback_interface = MozjsCallbackInterfaceHolder<T>(
+      implementing_object, context, global_object_proxy->wrapper_factory());
 }
 
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
 
+// Union type conversion is generated by a pump script.
+#include "cobalt/script/mozjs/union_type_conversion_impl.h"
+
 #endif  // COBALT_SCRIPT_MOZJS_CONVERSION_HELPERS_H_
diff --git a/src/cobalt/script/mozjs/convert_callback_return_value.h b/src/cobalt/script/mozjs/convert_callback_return_value.h
new file mode 100644
index 0000000..05c5245
--- /dev/null
+++ b/src/cobalt/script/mozjs/convert_callback_return_value.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_
+#define COBALT_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_
+
+#include "base/logging.h"
+#include "cobalt/script/callback_function.h"
+#include "cobalt/script/logging_exception_state.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// Helper template functions for Callback functions' return values before being
+// returned to Cobalt.
+// Converts the return value from JavaScript into the correct Cobalt type, or
+// sets the exception bit if conversion fails.
+template <typename R>
+CallbackResult<R> ConvertCallbackReturnValue(JSContext* context,
+                                             JS::HandleValue value) {
+  // TODO: Pass conversion flags to callback function return value if
+  // appropriate.
+  const int kConversionFlags = 0;
+  CallbackResult<R> callback_result;
+  LoggingExceptionState exception_state;
+  FromJSValue(context, value, kConversionFlags, &exception_state,
+              &callback_result.result);
+  callback_result.exception = exception_state.is_exception_set();
+  return callback_result;
+}
+
+template <>
+inline CallbackResult<void> ConvertCallbackReturnValue(JSContext* context,
+                                                       JS::HandleValue value) {
+  // No conversion necessary.
+  return CallbackResult<void>();
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_CONVERT_CALLBACK_RETURN_VALUE_H_
diff --git a/src/cobalt/script/mozjs/mozjs.gyp b/src/cobalt/script/mozjs/mozjs.gyp
index 886887d..58728de 100644
--- a/src/cobalt/script/mozjs/mozjs.gyp
+++ b/src/cobalt/script/mozjs/mozjs.gyp
@@ -19,10 +19,14 @@
       'type': 'static_library',
       'sources': [
         'conversion_helpers.cc',
+        'mozjs_callback_interface.cc',
+        'mozjs_debugger.cc',
         'mozjs_engine.cc',
         'mozjs_exception_state.cc',
         'mozjs_global_object_proxy.cc',
+        'mozjs_property_enumerator.cc',
         'mozjs_source_code.cc',
+        'proxy_handler.cc',
         'wrapper_factory.cc',
         'wrapper_private.cc',
       ],
@@ -30,7 +34,15 @@
         '<(DEPTH)/cobalt/script/script.gyp:script',
         '<(DEPTH)/third_party/mozjs/mozjs.gyp:mozjs_lib',
       ],
+      'defines': [ 'ENGINE_SUPPORTS_INT64', ],
+      'all_dependent_settings': {
+        'defines': [
+        # SpiderMonkey bindings implements indexed deleters.
+        'ENGINE_SUPPORTS_INDEXED_DELETERS',
+        'ENGINE_SUPPORTS_INT64', ],
+      },
     },
+
     {
       # Standalone executable for JS engine
       'target_name': 'mozjs',
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h b/src/cobalt/script/mozjs/mozjs_callback_function.h
index 85ff85e..bcdf94e 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h
@@ -25,6 +25,10 @@
 
 #include "base/logging.h"
 #include "cobalt/script/callback_function.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/convert_callback_return_value.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jscntxt.h"
 
 namespace cobalt {
 namespace script {
@@ -42,65 +46,251 @@
 class MozjsCallbackFunction<R(void)>
     : public CallbackFunction<R(void)> {
  public:
+  typedef CallbackFunction<R()> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run()
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 0;
+
+    JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL,
+        return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1>
 class MozjsCallbackFunction<R(A1)>
     : public CallbackFunction<R(A1)> {
  public:
+  typedef CallbackFunction<R(A1)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 1;
+
+    JS::Value args[1];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2>
 class MozjsCallbackFunction<R(A1, A2)>
     : public CallbackFunction<R(A1, A2)> {
  public:
+  typedef CallbackFunction<R(A1, A2)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 2;
+
+    JS::Value args[2];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2, typename A3>
 class MozjsCallbackFunction<R(A1, A2, A3)>
     : public CallbackFunction<R(A1, A2, A3)> {
  public:
+  typedef CallbackFunction<R(A1, A2, A3)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
       typename base::internal::CallbackParamTraits<A3>::ForwardType a3)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 3;
+
+    JS::Value args[3];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+    ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2, typename A3, typename A4>
 class MozjsCallbackFunction<R(A1, A2, A3, A4)>
     : public CallbackFunction<R(A1, A2, A3, A4)> {
  public:
+  typedef CallbackFunction<R(A1, A2, A3, A4)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
       typename base::internal::CallbackParamTraits<A3>::ForwardType a3,
       typename base::internal::CallbackParamTraits<A4>::ForwardType a4)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 4;
+
+    JS::Value args[4];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+    ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+    ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -108,6 +298,14 @@
 class MozjsCallbackFunction<R(A1, A2, A3, A4, A5)>
     : public CallbackFunction<R(A1, A2, A3, A4, A5)> {
  public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
@@ -115,9 +313,42 @@
       typename base::internal::CallbackParamTraits<A4>::ForwardType a4,
       typename base::internal::CallbackParamTraits<A5>::ForwardType a5)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 5;
+
+    JS::Value args[5];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+    ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+    ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+    ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -125,6 +356,14 @@
 class MozjsCallbackFunction<R(A1, A2, A3, A4, A5, A6)>
     : public CallbackFunction<R(A1, A2, A3, A4, A5, A6)> {
  public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
@@ -133,9 +372,43 @@
       typename base::internal::CallbackParamTraits<A5>::ForwardType a5,
       typename base::internal::CallbackParamTraits<A6>::ForwardType a6)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 6;
+
+    JS::Value args[6];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+    ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+    ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+    ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+    ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 template <typename R, typename A1, typename A2, typename A3, typename A4,
@@ -143,6 +416,14 @@
 class MozjsCallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)>
     : public CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> {
  public:
+  typedef CallbackFunction<R(A1, A2, A3, A4, A5, A6, A7)> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run(
       typename base::internal::CallbackParamTraits<A1>::ForwardType a1,
       typename base::internal::CallbackParamTraits<A2>::ForwardType a2,
@@ -152,9 +433,51 @@
       typename base::internal::CallbackParamTraits<A6>::ForwardType a6,
       typename base::internal::CallbackParamTraits<A7>::ForwardType a7)
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = 7;
+
+    JS::Value args[7];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    ToJSValue(context_, a1, auto_array_rooter.handleAt(0));
+    ToJSValue(context_, a2, auto_array_rooter.handleAt(1));
+    ToJSValue(context_, a3, auto_array_rooter.handleAt(2));
+    ToJSValue(context_, a4, auto_array_rooter.handleAt(3));
+    ToJSValue(context_, a5, auto_array_rooter.handleAt(4));
+    ToJSValue(context_, a6, auto_array_rooter.handleAt(5));
+    ToJSValue(context_, a7, auto_array_rooter.handleAt(6));
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
+};
+
+template <typename Signature>
+struct TypeTraits<CallbackFunction<Signature> > {
+  typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> >
+      ConversionType;
+  typedef const ScriptObject<CallbackFunction<Signature> >* ReturnType;
 };
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
index 510a8e4..fb4e78e 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
+++ b/src/cobalt/script/mozjs/mozjs_callback_function.h.pump
@@ -30,6 +30,10 @@
 
 #include "base/logging.h"
 #include "cobalt/script/callback_function.h"
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/convert_callback_return_value.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jscntxt.h"
 
 namespace cobalt {
 namespace script {
@@ -59,17 +63,68 @@
 ]]
 
  public:
+  typedef CallbackFunction<R($for ARG , [[A$(ARG)]])> BaseType;
+
+  explicit MozjsCallbackFunction(JSContext* context, JS::HandleObject function)
+      : context_(context), function_(function) {
+    DCHECK(context_);
+    DCHECK(JS_ObjectIsFunction(context_, function_));
+  }
+
   CallbackResult<R> Run($for ARG , [[
 
       typename base::internal::CallbackParamTraits<A$(ARG)>::ForwardType a$(ARG)]])
       const OVERRIDE {
-    NOTIMPLEMENTED();
-    return R();
+    JSAutoRequest auto_request(context_);
+    JSAutoCompartment auto_compartment(context_, function_);
+
+    // https://www.w3.org/TR/WebIDL/#es-invoking-callback-functions
+    // Callback 'this' is set to null, unless overridden by other specifications
+    JS::Value this_value(JS::NullValue());
+    JS::RootedValue return_value(context_);
+    const int kNumArguments = $(ARITY);
+
+
+$if ARITY > 0 [[
+    JS::Value args[$(ARITY)];
+    js::SetValueRangeToNull(args, kNumArguments);
+    js::AutoValueArray auto_array_rooter(context_, args, kNumArguments);
+    $for ARG [[ToJSValue(context_, a$(ARG), auto_array_rooter.handleAt($(ARG - 1)));
+    ]]
+
+    JSBool call_result = JS::Call(context_, this_value, function_,
+        kNumArguments, args, return_value.address());
+]] $else [[
+    JSBool call_result = JS::Call(context_, this_value, function_, 0, NULL,
+        return_value.address());
+]]
+
+
+    CallbackResult<R> callback_result;
+    if (!call_result) {
+      DLOG(WARNING) << "Exception in callback.";
+      callback_result.exception = true;
+    } else {
+      callback_result = ConvertCallbackReturnValue<R>(context_, return_value);
+    }
+    return callback_result;
   }
+
+  JSObject* handle() const { return function_; }
+
+ private:
+  JSContext* context_;
+  mutable JS::Heap<JSObject*> function_;
 };
 
 ]]
 
+template <typename Signature>
+struct TypeTraits<CallbackFunction<Signature> > {
+  typedef MozjsUserObjectHolder<MozjsCallbackFunction<Signature> > ConversionType;
+  typedef const ScriptObject<CallbackFunction<Signature> >* ReturnType;
+};
+
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_callback_function_holder.h b/src/cobalt/script/mozjs/mozjs_callback_function_holder.h
deleted file mode 100644
index bf1f91a..0000000
--- a/src/cobalt/script/mozjs/mozjs_callback_function_holder.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_
-#define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "cobalt/script/mozjs/mozjs_callback_function.h"
-#include "cobalt/script/script_object.h"
-
-namespace cobalt {
-namespace script {
-namespace mozjs {
-
-// Implementation of the ScriptObject interface for JSCCallbackFunctions.
-template <typename CallbackFunction>
-class MozjsCallbackFunctionHolder : public ScriptObject<CallbackFunction> {
- public:
-  typedef MozjsCallbackFunction<typename CallbackFunction::Signature>
-      MozjsCallbackFunctionClass;
-  typedef ScriptObject<CallbackFunction> BaseClass;
-
-  void RegisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); }
-
-  void DeregisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); }
-
-  const CallbackFunction* GetScriptObject() const OVERRIDE {
-    NOTIMPLEMENTED();
-    return NULL;
-  }
-
-  scoped_ptr<BaseClass> MakeCopy() const OVERRIDE {
-    NOTIMPLEMENTED();
-    return scoped_ptr<BaseClass>();
-  }
-
-  bool EqualTo(const BaseClass& other) const OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
-  }
-};
-
-}  // namespace mozjs
-}  // namespace script
-}  // namespace cobalt
-
-#endif  // COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_FUNCTION_HOLDER_H_
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface.cc b/src/cobalt/script/mozjs/mozjs_callback_interface.cc
new file mode 100644
index 0000000..90aa178
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_callback_interface.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/mozjs_callback_interface.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// Helper class to get the actual callable object from a JSObject implementing
+// a callback interface.
+// Returns true if a callable was found, and false if not.
+bool GetCallableForCallbackInterface(JSContext* context,
+                                     JS::HandleObject implementing_object,
+                                     const char* property_name,
+                                     JS::MutableHandleValue out_callable) {
+  DCHECK(implementing_object);
+  DCHECK(property_name);
+
+  if (JS_ObjectIsCallable(context, implementing_object)) {
+    out_callable.set(OBJECT_TO_JSVAL(implementing_object));
+    return true;
+  }
+  // Implementing object is not callable. Check for a callable property of the
+  // specified name.
+  JS::RootedValue property(context);
+  if (JS_GetProperty(context, implementing_object, property_name,
+                     property.address())) {
+    if (property.isObject() &&
+        JS_ObjectIsCallable(context, JSVAL_TO_OBJECT(property))) {
+      out_callable.set(property);
+      return true;
+    }
+  }
+
+  // Implementing object is not callable, nor does it have a callable property
+  // of the specified name.
+  return false;
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface.h b/src/cobalt/script/mozjs/mozjs_callback_interface.h
new file mode 100644
index 0000000..321682a
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_callback_interface.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_
+#define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_
+
+#include "cobalt/script/callback_interface_traits.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// Helper class to get the actual callable object from a JSObject implementing
+// a callback interface.
+// Returns true if a callable was found, and false if not.
+bool GetCallableForCallbackInterface(JSContext* context,
+                                     JS::HandleObject implementing_object,
+                                     const char* property_name,
+                                     JS::MutableHandleValue out_callable);
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_H_
diff --git a/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h b/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h
index d9f09ea..009acd5 100644
--- a/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h
+++ b/src/cobalt/script/mozjs/mozjs_callback_interface_holder.h
@@ -18,37 +18,30 @@
 #define COBALT_SCRIPT_MOZJS_MOZJS_CALLBACK_INTERFACE_HOLDER_H_
 
 #include "base/memory/scoped_ptr.h"
-#include "cobalt/script/script_object.h"
+#include "cobalt/script/callback_interface_traits.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
 
 namespace cobalt {
 namespace script {
 namespace mozjs {
 
-template <typename CallbackInterface>
-class MozjsCallbackInterfaceHolder : public ScriptObject<CallbackInterface> {
+template <typename MozjsCallbackInterface>
+class MozjsCallbackInterfaceHolder
+    : public MozjsUserObjectHolder<MozjsCallbackInterface> {
  public:
-  typedef typename CallbackInterfaceTraits<
-      CallbackInterface>::MozjsCallbackInterfaceClass MozjsCallbackInterface;
-  typedef ScriptObject<CallbackInterface> BaseClass;
+  typedef MozjsUserObjectHolder<MozjsCallbackInterface> BaseClass;
+  MozjsCallbackInterfaceHolder() {}
+  MozjsCallbackInterfaceHolder(JS::HandleObject object, JSContext* context,
+                               WrapperFactory* wrapper_factory)
+      : BaseClass(object, context, wrapper_factory) {}
+};
 
-  void RegisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); }
-
-  void DeregisterOwner(Wrappable* owner) OVERRIDE { NOTIMPLEMENTED(); }
-
-  const CallbackInterface* GetScriptObject() const OVERRIDE {
-    NOTIMPLEMENTED();
-    return NULL;
-  }
-
-  scoped_ptr<ScriptObject<CallbackInterface> > MakeCopy() const OVERRIDE {
-    NOTIMPLEMENTED();
-    return scoped_ptr<ScriptObject<CallbackInterface> >();
-  }
-
-  bool EqualTo(const BaseClass& other) const OVERRIDE {
-    NOTIMPLEMENTED();
-    return false;
-  }
+template <typename CallbackInterface>
+struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > {
+  typedef MozjsCallbackInterfaceHolder<typename CallbackInterfaceTraits<
+      CallbackInterface>::MozjsCallbackInterfaceClass> ConversionType;
+  typedef const ScriptObject<CallbackInterface>* ReturnType;
 };
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_debugger.cc b/src/cobalt/script/mozjs/mozjs_debugger.cc
new file mode 100644
index 0000000..e4ae668
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_debugger.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/mozjs_debugger.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace script {
+
+// Static factory method declared in public interface.
+scoped_ptr<ScriptDebugger> ScriptDebugger::CreateDebugger(
+    GlobalObjectProxy* global_object_proxy, Delegate* delegate) {
+  return scoped_ptr<ScriptDebugger>(
+      new mozjs::MozjsDebugger(global_object_proxy, delegate));
+}
+
+namespace mozjs {
+
+MozjsDebugger::MozjsDebugger(GlobalObjectProxy* global_object_proxy,
+                             Delegate* delegate) {
+  NOTIMPLEMENTED();
+}
+
+MozjsDebugger::~MozjsDebugger() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::Attach() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::Detach() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::Pause() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::Resume() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::SetBreakpoint(const std::string& script_id, int line_number,
+                                  int column_number) {
+  NOTIMPLEMENTED();
+}
+
+script::ScriptDebugger::PauseOnExceptionsState
+MozjsDebugger::SetPauseOnExceptions(PauseOnExceptionsState state) {
+  NOTIMPLEMENTED();
+  return kNone;
+}
+
+void MozjsDebugger::StepInto() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::StepOut() { NOTIMPLEMENTED(); }
+
+void MozjsDebugger::StepOver() { NOTIMPLEMENTED(); }
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_debugger.h b/src/cobalt/script/mozjs/mozjs_debugger.h
new file mode 100644
index 0000000..63fd7f2
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_debugger.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_
+#define COBALT_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_
+
+#include <string>
+
+#include "cobalt/script/script_debugger.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+class MozjsDebugger : public ScriptDebugger {
+ public:
+  MozjsDebugger(GlobalObjectProxy* global_object_proxy, Delegate* delegate);
+  ~MozjsDebugger() OVERRIDE;
+
+  // Implementation of ScriptDebugger.
+  void Attach() OVERRIDE;
+  void Detach() OVERRIDE;
+  void Pause() OVERRIDE;
+  void Resume() OVERRIDE;
+  void SetBreakpoint(const std::string& script_id, int line_number,
+                     int column_number) OVERRIDE;
+  PauseOnExceptionsState SetPauseOnExceptions(
+      PauseOnExceptionsState state) OVERRIDE;
+  void StepInto() OVERRIDE;
+  void StepOut() OVERRIDE;
+  void StepOver() OVERRIDE;
+};
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_MOZJS_DEBUGGER_H_
diff --git a/src/cobalt/script/mozjs/mozjs_exception_state.cc b/src/cobalt/script/mozjs/mozjs_exception_state.cc
index 607c123..a4c575b 100644
--- a/src/cobalt/script/mozjs/mozjs_exception_state.cc
+++ b/src/cobalt/script/mozjs/mozjs_exception_state.cc
@@ -55,18 +55,15 @@
 void MozjsExceptionState::SetSimpleException(
     SimpleExceptionType simple_exception, const std::string& message) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(!is_exception_set_);
 
   std::stringstream stream;
   stream << SimpleExceptionToString(simple_exception) << ": " << message;
-  // JS_ReportWarning first builds an error message from the given sprintf-style
+  // JS_ReportError first builds an error message from the given sprintf-style
   // format string and any additional arguments passed after it. The resulting
   // error message is passed to the context's JSErrorReporter callback.
-  JS_ReportWarning(context_, stream.str().c_str());
-}
-
-bool MozjsExceptionState::IsExceptionSet() {
-  // TODO: Implement this.
-  return false;
+  JS_ReportError(context_, stream.str().c_str());
+  is_exception_set_ = true;
 }
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs/mozjs_exception_state.h b/src/cobalt/script/mozjs/mozjs_exception_state.h
index af8d13b..4a3c11d 100644
--- a/src/cobalt/script/mozjs/mozjs_exception_state.h
+++ b/src/cobalt/script/mozjs/mozjs_exception_state.h
@@ -28,15 +28,17 @@
 
 class MozjsExceptionState : public ExceptionState {
  public:
-  explicit MozjsExceptionState(JSContext* context) : context_(context) {}
+  explicit MozjsExceptionState(JSContext* context)
+      : is_exception_set_(false), context_(context) {}
   // ExceptionState interface
   void SetException(const scoped_refptr<ScriptException>& exception) OVERRIDE;
   void SetSimpleException(SimpleExceptionType simple_exception,
                           const std::string& message) OVERRIDE;
 
-  bool IsExceptionSet();
+  bool is_exception_set() const { return is_exception_set_; }
 
  private:
+  bool is_exception_set_;
   JSContext* context_;
   base::ThreadChecker thread_checker_;
 };
diff --git a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
index 0f394ef..43c45bc 100644
--- a/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
+++ b/src/cobalt/script/mozjs/mozjs_global_object_proxy.cc
@@ -184,8 +184,9 @@
                                   const scoped_refptr<Wrappable>& impl) {
   JSAutoRequest auto_request(context_);
   JSAutoCompartment auto_comparment(context_, global_object_);
-  JS::RootedObject wrapper(context_, wrapper_factory_->GetWrapper(impl));
-  JS::Value wrapper_value = JS::ObjectValue(*wrapper.get());
+  JS::RootedObject wrapper_proxy(context_,
+                                 wrapper_factory_->GetWrapperProxy(impl));
+  JS::Value wrapper_value = OBJECT_TO_JSVAL(wrapper_proxy);
   bool success = JS_SetProperty(context_, global_object_, identifier.c_str(),
                                 &wrapper_value);
   DCHECK(success);
diff --git a/src/cobalt/script/mozjs/mozjs_object_handle.h b/src/cobalt/script/mozjs/mozjs_object_handle.h
index 4c2d5d0..6e59df8 100644
--- a/src/cobalt/script/mozjs/mozjs_object_handle.h
+++ b/src/cobalt/script/mozjs/mozjs_object_handle.h
@@ -18,6 +18,7 @@
 
 #include "base/optional.h"
 #include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
 #include "cobalt/script/opaque_handle.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 
@@ -31,12 +32,12 @@
 // a ScriptObject<OpaqueHandle>.
 class MozjsObjectHandle : public OpaqueHandle {
  public:
-  typedef MozjsUserObjectHolder<MozjsObjectHandle> HolderType;
   typedef OpaqueHandle BaseType;
   JSObject* handle() const { return handle_; }
 
  private:
-  explicit MozjsObjectHandle(JS::HandleObject object) : handle_(object) {}
+  MozjsObjectHandle(JSContext*, JS::HandleObject object)
+      : handle_(object) {}
   ~MozjsObjectHandle() {}
 
   // Note that this class does not root this JS::Heap<> object. Rooting of this
@@ -50,6 +51,12 @@
 
 typedef MozjsUserObjectHolder<MozjsObjectHandle> MozjsObjectHandleHolder;
 
+template <>
+struct TypeTraits<OpaqueHandle> {
+  typedef MozjsObjectHandleHolder ConversionType;
+  typedef const ScriptObject<OpaqueHandle>* ReturnType;
+};
+
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_property_enumerator.cc b/src/cobalt/script/mozjs/mozjs_property_enumerator.cc
new file mode 100644
index 0000000..10db0b5
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_property_enumerator.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "cobalt/script/mozjs/mozjs_property_enumerator.h"
+
+#include "base/logging.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+MozjsPropertyEnumerator::MozjsPropertyEnumerator(JSContext* context,
+                                                 JS::AutoIdVector* properties)
+    : context_(context), properties_(properties) {}
+
+void MozjsPropertyEnumerator::AddProperty(const std::string& property_name) {
+  JS::RootedString property_string(
+      context_, JS_NewStringCopyZ(context_, property_name.c_str()));
+  JS::RootedId id(context_);
+  if (JS_ValueToId(context_, STRING_TO_JSVAL(property_string), id.address())) {
+    properties_->append(id);
+  } else {
+    NOTREACHED();
+  }
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/mozjs_property_enumerator.h b/src/cobalt/script/mozjs/mozjs_property_enumerator.h
new file mode 100644
index 0000000..6ad2553
--- /dev/null
+++ b/src/cobalt/script/mozjs/mozjs_property_enumerator.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_
+#define COBALT_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "cobalt/script/property_enumerator.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+class MozjsPropertyEnumerator : public cobalt::script::PropertyEnumerator {
+ public:
+  MozjsPropertyEnumerator(JSContext* context, JS::AutoIdVector* properties);
+  void AddProperty(const std::string& property_name) OVERRIDE;
+
+ private:
+  JSContext* context_;
+  JS::AutoIdVector* properties_;
+};
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_MOZJS_PROPERTY_ENUMERATOR_H_
diff --git a/src/cobalt/script/mozjs/mozjs_user_object_holder.h b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
index bcd0cf1..0551bff 100644
--- a/src/cobalt/script/mozjs/mozjs_user_object_holder.h
+++ b/src/cobalt/script/mozjs/mozjs_user_object_holder.h
@@ -19,6 +19,7 @@
 #include "cobalt/base/polymorphic_downcast.h"
 #include "cobalt/script/mozjs/wrapper_factory.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "cobalt/script/script_object.h"
 #include "third_party/mozjs/js/src/jsapi.h"
 
 namespace cobalt {
@@ -39,9 +40,9 @@
 
   MozjsUserObjectHolder() : context_(NULL), wrapper_factory_(NULL) {}
 
-  explicit MozjsUserObjectHolder(JS::HandleObject object, JSContext* context,
-                                 WrapperFactory* wrapper_factory)
-      : object_handle_(MozjsUserObjectType(object)),
+  MozjsUserObjectHolder(JS::HandleObject object, JSContext* context,
+                        WrapperFactory* wrapper_factory)
+      : object_handle_(MozjsUserObjectType(context, object)),
         context_(context),
         wrapper_factory_(wrapper_factory) {}
 
diff --git a/src/cobalt/script/mozjs/mozjs_wrapper_handle.h b/src/cobalt/script/mozjs/mozjs_wrapper_handle.h
index df014d9..3f8ef37 100644
--- a/src/cobalt/script/mozjs/mozjs_wrapper_handle.h
+++ b/src/cobalt/script/mozjs/mozjs_wrapper_handle.h
@@ -35,12 +35,12 @@
     weak_wrapper_private_ = wrapper_private->AsWeakPtr();
   }
 
-  static JSObject* GetJSObject(const Wrappable::WeakWrapperHandle* handle) {
+  static JSObject* GetObjectProxy(const Wrappable::WeakWrapperHandle* handle) {
     if (handle) {
       const MozjsWrapperHandle* mozjs_handle =
           base::polymorphic_downcast<const MozjsWrapperHandle*>(handle);
       if (mozjs_handle->weak_wrapper_private_) {
-        return mozjs_handle->weak_wrapper_private_->js_object();
+        return mozjs_handle->weak_wrapper_private_->js_object_proxy();
       }
     }
     return NULL;
diff --git a/src/cobalt/script/mozjs/proxy_handler.cc b/src/cobalt/script/mozjs/proxy_handler.cc
new file mode 100644
index 0000000..17849cd
--- /dev/null
+++ b/src/cobalt/script/mozjs/proxy_handler.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "cobalt/script/mozjs/proxy_handler.h"
+
+#include "cobalt/script/mozjs/conversion_helpers.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+ProxyHandler::ProxyHandler(const IndexedPropertyHooks& indexed_hooks,
+                           const NamedPropertyHooks& named_hooks)
+    : js::DirectProxyHandler(NULL),
+      indexed_property_hooks_(indexed_hooks),
+      named_property_hooks_(named_hooks) {
+  // If an interface supports named/indexed properties, they must have a hook to
+  // check if the name/index is supported and to enumerate the properties.
+  if (supports_named_properties()) {
+    DCHECK(named_property_hooks_.is_supported);
+    DCHECK(named_property_hooks_.enumerate_supported);
+  }
+  if (supports_indexed_properties()) {
+    DCHECK(indexed_property_hooks_.is_supported);
+    DCHECK(indexed_property_hooks_.enumerate_supported);
+  }
+}
+
+JSObject* ProxyHandler::NewProxy(JSContext* context, JSObject* object,
+                                 JSObject* prototype, JSObject* parent,
+                                 ProxyHandler* handler) {
+  JS::RootedValue as_value(context, OBJECT_TO_JSVAL(object));
+  return js::NewProxyObject(context, handler, as_value, prototype, parent);
+}
+
+bool ProxyHandler::getPropertyDescriptor(JSContext* context,
+                                         JS::HandleObject proxy,
+                                         JS::HandleId id,
+                                         JSPropertyDescriptor* descriptor,
+                                         unsigned flags) {
+  // https://www.w3.org/TR/WebIDL/#getownproperty
+  if (supports_named_properties() || supports_indexed_properties()) {
+    // Convert the id to a JSValue, so we can easily convert it to Uint32 and
+    // JSString.
+    JS::RootedValue id_value(context);
+    if (!JS_IdToValue(context, id, id_value.address())) {
+      NOTREACHED();
+      return false;
+    }
+    JS::RootedObject object(context, js::GetProxyTargetObject(proxy));
+    if (supports_indexed_properties()) {
+      // If the interface supports indexed properties and this is an array index
+      // property name, and it is a supported property index.
+      uint32_t index;
+      if (IsArrayIndexPropertyName(context, id_value, &index) &&
+          IsSupportedIndex(context, object, index)) {
+        descriptor->obj = object;
+        descriptor->attrs = JSPROP_SHARED | JSPROP_INDEX | JSPROP_ENUMERATE;
+        descriptor->getter = indexed_property_hooks_.getter;
+        if (indexed_property_hooks_.setter) {
+          descriptor->setter = indexed_property_hooks_.setter;
+        } else {
+          descriptor->attrs |= JSPROP_READONLY;
+        }
+        return true;
+      }
+    }
+    if (supports_named_properties()) {
+      std::string property_name;
+      MozjsExceptionState exception_state(context);
+      FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+                  &property_name);
+      if (exception_state.is_exception_set()) {
+        // The ID should be an integer or a string, so we shouldn't have any
+        // exceptions converting to string.
+        NOTREACHED();
+        return false;
+      }
+      if (IsNamedPropertyVisible(context, object, property_name)) {
+        descriptor->obj = object;
+        descriptor->attrs = JSPROP_SHARED | JSPROP_ENUMERATE;
+        descriptor->getter = named_property_hooks_.getter;
+        if (named_property_hooks_.setter) {
+          descriptor->setter = named_property_hooks_.setter;
+        } else {
+          descriptor->attrs |= JSPROP_READONLY;
+        }
+        return true;
+      }
+    }
+  }
+  return js::DirectProxyHandler::getPropertyDescriptor(context, proxy, id,
+                                                       descriptor, flags);
+}
+
+bool ProxyHandler::delete_(JSContext* context, JS::HandleObject proxy,
+                           JS::HandleId id, bool* succeeded) {
+  // https://www.w3.org/TR/WebIDL/#delete
+  if (supports_named_properties() || supports_indexed_properties()) {
+    // Convert the id to a JSValue, so we can easily convert it to Uint32 and
+    // JSString.
+    JS::RootedValue id_value(context);
+    if (!JS_IdToValue(context, id, id_value.address())) {
+      NOTREACHED();
+      return false;
+    }
+    DCHECK(js::IsProxy(proxy));
+    JS::RootedObject object(context, js::GetProxyTargetObject(proxy));
+    if (supports_indexed_properties()) {
+      // If the interface supports indexed properties and this is an array index
+      // property name, and it is a supported property index.
+      uint32_t index;
+      // 1. If O supports indexed properties and P is an array index property
+      // name,
+      //    then:
+      if (IsArrayIndexPropertyName(context, id_value, &index)) {
+        if (!IsSupportedIndex(context, object, index)) {
+          // 1.2. If index is not a supported property index, then return true.
+          *succeeded = true;
+        } else if (!indexed_property_hooks_.deleter) {
+          // 1.3. If O does not implement an interface with an indexed property
+          //    deleter, then Reject.
+          *succeeded = false;
+        } else {
+          *succeeded = indexed_property_hooks_.deleter(context, object, index);
+        }
+        return true;
+      }
+    }
+    if (supports_named_properties()) {
+      std::string property_name;
+      MozjsExceptionState exception_state(context);
+      FromJSValue(context, id_value, kNoConversionFlags, &exception_state,
+                  &property_name);
+      if (exception_state.is_exception_set()) {
+        // The ID should be an integer or a string, so we shouldn't have any
+        // exceptions converting to string.
+        NOTREACHED();
+        return false;
+      }
+      if (IsNamedPropertyVisible(context, object, property_name)) {
+        if (!named_property_hooks_.deleter) {
+          *succeeded = false;
+        } else {
+          *succeeded =
+              named_property_hooks_.deleter(context, object, property_name);
+        }
+        return true;
+      }
+    }
+  }
+  return js::DirectProxyHandler::delete_(context, proxy, id, succeeded);
+}
+
+bool ProxyHandler::enumerate(JSContext* context, JS::HandleObject proxy,
+                             JS::AutoIdVector& properties) {
+  // https://www.w3.org/TR/WebIDL/#property-enumeration
+  // Indexed properties go first, then named properties, then everything else.
+  JS::RootedObject object(context, js::GetProxyTargetObject(proxy));
+  if (supports_indexed_properties()) {
+    indexed_property_hooks_.enumerate_supported(context, object, &properties);
+  }
+  if (supports_named_properties()) {
+    named_property_hooks_.enumerate_supported(context, object, &properties);
+  }
+  return js::DirectProxyHandler::enumerate(context, proxy, properties);
+}
+
+bool ProxyHandler::IsSupportedIndex(JSContext* context, JS::HandleObject object,
+                                    uint32_t index) {
+  DCHECK(indexed_property_hooks_.is_supported);
+  return indexed_property_hooks_.is_supported(context, object, index);
+}
+
+bool ProxyHandler::IsSupportedName(JSContext* context, JS::HandleObject object,
+                                   const std::string& name) {
+  DCHECK(named_property_hooks_.is_supported);
+  return named_property_hooks_.is_supported(context, object, name);
+}
+
+bool ProxyHandler::IsArrayIndexPropertyName(JSContext* context,
+                                            JS::HandleValue property_value,
+                                            uint32_t* out_index) {
+  // https://www.w3.org/TR/WebIDL/#dfn-array-index-property-name
+  // 1. Let i be ToUint32(P).
+  uint32_t index;
+  if (!JS::ToUint32(context, property_value, &index)) {
+    return false;
+  }
+
+  // 3. If i = 2^32 - 1, then return false.
+  if (index == 0xFFFFFFFF) {
+    return false;
+  }
+
+  // 2. Let s be ToString(i).
+  // 3. If s != P then return false.
+  JSBool are_equal;
+  JS::RootedString index_as_string(
+      context, JS_ValueToString(context, UINT_TO_JSVAL(index)));
+  if (!JS_LooselyEqual(context, JS::StringValue(index_as_string),
+                       property_value, &are_equal) ||
+      !are_equal) {
+    return false;
+  }
+
+  // 4. Return true.
+  *out_index = index;
+  return true;
+}
+
+bool ProxyHandler::IsNamedPropertyVisible(JSContext* context,
+                                          JS::HandleObject object,
+                                          const std::string& property_name) {
+  // Named property visiblity algorithm.
+  // https://www.w3.org/TR/WebIDL/#dfn-named-property-visibility
+
+  // 1. If P is an unforgeable property name on O, then return false.
+  // 2. If O implements an interface with an [Unforgeable]-annotated attribute
+  //    whose identifier is P, then return false.
+  // TODO: Implement Unforgeable extended attribute.
+
+  // 3. If P is not a supported property name of O, then return false.
+  if (!IsSupportedName(context, object, property_name)) {
+    return false;
+  }
+
+  // 4. If O implements an interface that has the [OverrideBuiltins] extended
+  // attribute, then return true.
+  // TODO: Implement OverrideBuiltins extended attribute
+
+  // 5. If O has an own property named P, then return false.
+  // 6~7. ( Walk the prototype chain and if the prootype has P, return false)
+
+  JSBool found_property;
+  if (!JS_HasProperty(context, object, property_name.c_str(),
+                      &found_property)) {
+    // An error occurred searching for the property.
+    NOTREACHED();
+    return true;
+  }
+  return !found_property;
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/proxy_handler.h b/src/cobalt/script/mozjs/proxy_handler.h
new file mode 100644
index 0000000..e6a7c54
--- /dev/null
+++ b/src/cobalt/script/mozjs/proxy_handler.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
+#define COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jsproxy.h"
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+// SpiderMonkey has a concept of a Proxy object which is associated with another
+// arbitrary object and a js::BaseProxyHandler interface. The handler interface
+// provides a number of traps for providing custom implementations of
+// fundamental ECMAScript operations such as getPropertyDescriptor.
+//
+// The implementation of each trap in the js::DirectProxyHandler class simply
+// forwards each trap to the target object.
+//
+// In defining a JSClass a number of function pointers can be set that will
+// be called when getting, setting, deleting, etc. a property, but these do not
+// map well onto the Web IDL spec for implementing interfaces that support named
+// and indexed properties.
+//
+// See third_party/mozjs/js/src/jsproxy.h for more details.
+//
+// ProxyHandler provides custom traps for getPropertyDescriptor, delete_, and
+// enumerate to implement interfaces that support named and indexed properties.
+class ProxyHandler : public js::DirectProxyHandler {
+ public:
+  typedef bool (*IsSupportedIndexFunction)(JSContext*, JS::HandleObject,
+                                           uint32_t);
+  typedef bool (*IsSupportedNameFunction)(JSContext*, JS::HandleObject,
+                                          const std::string&);
+  typedef void (*EnumerateSupportedIndexesFunction)(JSContext*,
+                                                    JS::HandleObject,
+                                                    JS::AutoIdVector*);
+  typedef void (*EnumerateSupportedNamesFunction)(JSContext*, JS::HandleObject,
+                                                  JS::AutoIdVector*);
+  typedef bool (*IndexedDeleteFunction)(JSContext*, JS::HandleObject, uint32_t);
+  typedef bool (*NamedDeleteFunction)(JSContext*, JS::HandleObject,
+                                      const std::string&);
+
+  // Hooks for interfaces that support indexed properties.
+  struct IndexedPropertyHooks {
+    IsSupportedIndexFunction is_supported;
+    EnumerateSupportedIndexesFunction enumerate_supported;
+    JSPropertyOp getter;
+    JSStrictPropertyOp setter;
+    IndexedDeleteFunction deleter;
+  };
+
+  // Hooks for interfaces that support named properties.
+  struct NamedPropertyHooks {
+    IsSupportedNameFunction is_supported;
+    EnumerateSupportedNamesFunction enumerate_supported;
+    JSPropertyOp getter;
+    JSStrictPropertyOp setter;
+    NamedDeleteFunction deleter;
+  };
+
+  static JSObject* NewProxy(JSContext* context, JSObject* object,
+                            JSObject* prototype, JSObject* parent,
+                            ProxyHandler* handler);
+
+  // Construct a new ProxyHandler with the provided hooks.
+  ProxyHandler(const IndexedPropertyHooks& indexed_hooks,
+               const NamedPropertyHooks& named_hooks);
+
+  // Overridden fundamental traps.
+  bool getPropertyDescriptor(JSContext* context, JS::HandleObject proxy,
+                             JS::HandleId id, JSPropertyDescriptor* descriptor,
+                             unsigned flags) OVERRIDE;
+  bool delete_(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
+               bool* succeeded) OVERRIDE;
+  bool enumerate(JSContext* context, JS::HandleObject proxy,
+                 JS::AutoIdVector& properties) OVERRIDE;  // NOLINT[runtime/references]
+
+  // The derived traps in js::DirectProxyHandler are not implemented in terms of
+  // the fundamental traps, where the traps in js::BaseProxyHandler are.
+  // Redefining the derived traps to be in terms of the fundamental traps means
+  // that we only need to override the fundamental traps when implementing
+  // custom behavior for i.e. interfaces that support named properties.
+  bool has(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
+           bool* bp) OVERRIDE {
+    return js::BaseProxyHandler::has(context, proxy, id, bp);
+  }
+
+  bool hasOwn(JSContext* context, JS::HandleObject proxy, JS::HandleId id,
+              bool* bp) OVERRIDE {
+    return js::BaseProxyHandler::hasOwn(context, proxy, id, bp);
+  }
+
+  bool get(JSContext* context, JS::HandleObject proxy,
+           JS::HandleObject receiver, JS::HandleId id,
+           JS::MutableHandleValue vp) OVERRIDE {
+    return js::BaseProxyHandler::get(context, proxy, receiver, id, vp);
+  }
+
+  bool set(JSContext* context, JS::HandleObject proxy,
+           JS::HandleObject receiver, JS::HandleId id, bool strict,
+           JS::MutableHandleValue vp) OVERRIDE {
+    return js::BaseProxyHandler::set(context, proxy, receiver, id, strict, vp);
+  }
+
+  bool keys(JSContext* context, JS::HandleObject proxy,
+            JS::AutoIdVector& props) OVERRIDE {  // NOLINT[runtime/references]
+    return js::BaseProxyHandler::keys(context, proxy, props);
+  }
+
+  bool iterate(JSContext* context, JS::HandleObject proxy, unsigned flags,
+               JS::MutableHandleValue vp) OVERRIDE {
+    return js::BaseProxyHandler::iterate(context, proxy, flags, vp);
+  }
+
+ private:
+  bool supports_named_properties() {
+    return named_property_hooks_.getter != NULL;
+  }
+
+  bool supports_indexed_properties() {
+    return indexed_property_hooks_.getter != NULL;
+  }
+
+  bool IsSupportedIndex(JSContext* context, JS::HandleObject object,
+                        uint32_t index);
+
+  bool IsSupportedName(JSContext* context, JS::HandleObject object,
+                       const std::string& name);
+
+  bool IsArrayIndexPropertyName(JSContext* context,
+                                JS::HandleValue property_value,
+                                uint32_t* out_index);
+
+  bool IsNamedPropertyVisible(JSContext* context, JS::HandleObject object,
+                              const std::string& property_name);
+
+  IndexedPropertyHooks indexed_property_hooks_;
+  NamedPropertyHooks named_property_hooks_;
+};
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_PROXY_HANDLER_H_
diff --git a/src/cobalt/script/mozjs/type_traits.h b/src/cobalt/script/mozjs/type_traits.h
index 6d17ea3..336db63 100644
--- a/src/cobalt/script/mozjs/type_traits.h
+++ b/src/cobalt/script/mozjs/type_traits.h
@@ -17,13 +17,6 @@
 #ifndef COBALT_SCRIPT_MOZJS_TYPE_TRAITS_H_
 #define COBALT_SCRIPT_MOZJS_TYPE_TRAITS_H_
 
-#include "cobalt/script/callback_interface_traits.h"
-#include "cobalt/script/mozjs/mozjs_callback_function_holder.h"
-#include "cobalt/script/mozjs/mozjs_callback_interface_holder.h"
-#include "cobalt/script/mozjs/mozjs_object_handle.h"
-#include "cobalt/script/opaque_handle.h"
-#include "cobalt/script/script_object.h"
-
 namespace cobalt {
 namespace script {
 namespace mozjs {
@@ -36,24 +29,6 @@
   typedef T ReturnType;
 };
 
-template <>
-struct TypeTraits<OpaqueHandle> {
-  typedef MozjsObjectHandleHolder ConversionType;
-  typedef const ScriptObject<OpaqueHandle>* ReturnType;
-};
-
-template <typename Sig>
-struct TypeTraits<CallbackFunction<Sig> > {
-  typedef MozjsCallbackFunctionHolder<CallbackFunction<Sig> > ConversionType;
-  typedef const ScriptObject<CallbackFunction<Sig> >* ReturnType;
-};
-
-template <typename CallbackInterface>
-struct TypeTraits<CallbackInterfaceTraits<CallbackInterface> > {
-  typedef MozjsCallbackInterfaceHolder<CallbackInterface> ConversionType;
-  typedef const ScriptObject<CallbackInterface>* ReturnType;
-};
-
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/union_type_conversion_forward.h b/src/cobalt/script/mozjs/union_type_conversion_forward.h
new file mode 100644
index 0000000..c001f65
--- /dev/null
+++ b/src/cobalt/script/mozjs/union_type_conversion_forward.h
@@ -0,0 +1,70 @@
+// This file was GENERATED by command:
+//     pump.py union_type_conversion_forward.h.pump
+// DO NOT EDIT BY HAND!!!
+
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
+#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
+
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/union_type.h"
+
+// Forward declaration for ToJSValue and FromJSValue for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+template <typename T1, typename T2>
+void ToJSValue(JSContext* context, const script::UnionType2<T1, T2>& in_union,
+               JS::MutableHandleValue out_value);
+
+template <typename T1, typename T2>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType2<T1, T2>* out_union);
+
+template <typename T1, typename T2, typename T3>
+void ToJSValue(JSContext* context,
+               const script::UnionType3<T1, T2, T3>& in_union,
+               JS::MutableHandleValue out_value);
+
+template <typename T1, typename T2, typename T3>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType3<T1, T2, T3>* out_union);
+
+template <typename T1, typename T2, typename T3, typename T4>
+void ToJSValue(JSContext* context,
+               const script::UnionType4<T1, T2, T3, T4>& in_union,
+               JS::MutableHandleValue out_value);
+
+template <typename T1, typename T2, typename T3, typename T4>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType4<T1, T2, T3, T4>* out_union);
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump b/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump
new file mode 100644
index 0000000..876b511
--- /dev/null
+++ b/src/cobalt/script/mozjs/union_type_conversion_forward.h.pump
@@ -0,0 +1,60 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$$ Maximum number of different member types in a union.
+$var MAX_MEMBERS = 4
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
+#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
+
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/union_type.h"
+
+// Forward declaration for ToJSValue and FromJSValue for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+$range NUM_MEMBERS 2..MAX_MEMBERS
+$for NUM_MEMBERS [[
+$range TYPE 1..NUM_MEMBERS
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void ToJSValue(JSContext* context, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union, JS::MutableHandleValue out_value);
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union);
+
+]]  $$ for NUM_MEMBERS
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_FORWARD_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_impl.h b/src/cobalt/script/mozjs/union_type_conversion_impl.h
new file mode 100644
index 0000000..5d0076f
--- /dev/null
+++ b/src/cobalt/script/mozjs/union_type_conversion_impl.h
@@ -0,0 +1,635 @@
+// This file was GENERATED by command:
+//     pump.py union_type_conversion_impl.h.pump
+// DO NOT EDIT BY HAND!!!
+
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
+#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
+
+#include "cobalt/base/type_id.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/union_type.h"
+
+// Conversion to/from JS::Value for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+template <typename T1, typename T2>
+void ToJSValue(JSContext* context, const script::UnionType2<T1, T2>& in_union,
+               JS::MutableHandleValue out_value) {
+  if (in_union.template IsType<T1>()) {
+    ToJSValue(context, in_union.template AsType<T1>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T2>()) {
+    ToJSValue(context, in_union.template AsType<T2>(), out_value);
+    return;
+  }
+  NOTREACHED();
+  out_value.setUndefined();
+}
+
+template <typename T1, typename T2>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType2<T1, T2>* out_union) {
+  DCHECK_EQ(0, conversion_flags);
+  // JS -> IDL type conversion procedure described here:
+  // http://heycam.github.io/webidl/#es-union
+
+  // 1. If the union type includes a nullable type and V is null or undefined,
+  // then return the IDL value null.
+  if (value.isNull() || value.isUndefined()) {
+    // If the type was nullable or undefined, we should have caught that as a
+    // part of the base::optional<T> conversion.
+    NOTREACHED();
+    return;
+  }
+  // Typedef for readability.
+  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
+
+  // Forward declare all potential types
+  T1 t1;
+  T2 t2;
+
+  // 3.1 If types includes an interface type that V implements, then return the
+  //     IDL value that is a reference to the object V.
+  // 3.2 If types includes object, then return the IDL value that is a reference
+  //     to the object V.
+  //
+  // The specification doesn't dictate what should happen if V implements more
+  // than one of the interfaces. For example, if V implements interface B and
+  // interface B inherits from interface A, what happens if both A and B are
+  // union members? Blink doesn't seem to do anything special for this case.
+  // Just choose the first interface in the flattened members that matches.
+  if (value.isObject()) {
+    JS::RootedObject rooted_object(context);
+    bool success = JS_ValueToObject(context, value, rooted_object.address());
+    DCHECK(success);
+    MozjsGlobalObjectProxy* global_object_proxy =
+        static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+    const WrapperFactory* wrapper_factory =
+        global_object_proxy->wrapper_factory();
+    if (UnionTypeTraitsT1::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT1::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType2<T1, T2>(t1);
+      return;
+    }
+    if (UnionTypeTraitsT2::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT2::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType2<T1, T2>(t2);
+      return;
+    }
+  }
+
+  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
+  //       TypedArrayName, callback functions, dictionary, array type.
+  //       And sequences if necessary.
+
+  // 14. If V is a Boolean value, then:
+  //   1. If types includes a boolean, then return the result of converting V
+  //      to boolean.
+  if (value.isBoolean()) {
+    if (UnionTypeTraitsT1::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType2<T1, T2>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType2<T1, T2>(t2);
+      return;
+    }
+  }
+
+  // 15. If V is a Number value, then:
+  //   1. If types includes a numeric type, then return the result of converting
+  //      V to that numeric type.
+  if (value.isNumber()) {
+    if (UnionTypeTraitsT1::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType2<T1, T2>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType2<T1, T2>(t2);
+      return;
+    }
+  }
+
+  // 16. If types includes a string type, then return the result of converting V
+  // to that type.
+  if (value.isString()) {
+    if (UnionTypeTraitsT1::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType2<T1, T2>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType2<T1, T2>(t2);
+      return;
+    }
+  }
+
+  // 17. If types includes a numeric type, then return the result of converting
+  // V to that numeric type.
+  if (UnionTypeTraitsT1::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType2<T1, T2>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType2<T1, T2>(t2);
+    return;
+  }
+  // 18. If types includes a boolean, then return the result of converting V to
+  // boolean.
+  if (UnionTypeTraitsT1::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType2<T1, T2>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType2<T1, T2>(t2);
+    return;
+  }
+  // 19. Throw a TypeError.
+  exception_state->SetSimpleException(
+      ExceptionState::kTypeError, "Value is not a member of the union type.");
+}
+
+template <typename T1, typename T2, typename T3>
+void ToJSValue(JSContext* context,
+               const script::UnionType3<T1, T2, T3>& in_union,
+               JS::MutableHandleValue out_value) {
+  if (in_union.template IsType<T1>()) {
+    ToJSValue(context, in_union.template AsType<T1>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T2>()) {
+    ToJSValue(context, in_union.template AsType<T2>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T3>()) {
+    ToJSValue(context, in_union.template AsType<T3>(), out_value);
+    return;
+  }
+  NOTREACHED();
+  out_value.setUndefined();
+}
+
+template <typename T1, typename T2, typename T3>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType3<T1, T2, T3>* out_union) {
+  DCHECK_EQ(0, conversion_flags);
+  // JS -> IDL type conversion procedure described here:
+  // http://heycam.github.io/webidl/#es-union
+
+  // 1. If the union type includes a nullable type and V is null or undefined,
+  // then return the IDL value null.
+  if (value.isNull() || value.isUndefined()) {
+    // If the type was nullable or undefined, we should have caught that as a
+    // part of the base::optional<T> conversion.
+    NOTREACHED();
+    return;
+  }
+  // Typedef for readability.
+  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3;
+
+  // Forward declare all potential types
+  T1 t1;
+  T2 t2;
+  T3 t3;
+
+  // 3.1 If types includes an interface type that V implements, then return the
+  //     IDL value that is a reference to the object V.
+  // 3.2 If types includes object, then return the IDL value that is a reference
+  //     to the object V.
+  //
+  // The specification doesn't dictate what should happen if V implements more
+  // than one of the interfaces. For example, if V implements interface B and
+  // interface B inherits from interface A, what happens if both A and B are
+  // union members? Blink doesn't seem to do anything special for this case.
+  // Just choose the first interface in the flattened members that matches.
+  if (value.isObject()) {
+    JS::RootedObject rooted_object(context);
+    bool success = JS_ValueToObject(context, value, rooted_object.address());
+    DCHECK(success);
+    MozjsGlobalObjectProxy* global_object_proxy =
+        static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+    const WrapperFactory* wrapper_factory =
+        global_object_proxy->wrapper_factory();
+    if (UnionTypeTraitsT1::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT1::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType3<T1, T2, T3>(t1);
+      return;
+    }
+    if (UnionTypeTraitsT2::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT2::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType3<T1, T2, T3>(t2);
+      return;
+    }
+    if (UnionTypeTraitsT3::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT3::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType3<T1, T2, T3>(t3);
+      return;
+    }
+  }
+
+  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
+  //       TypedArrayName, callback functions, dictionary, array type.
+  //       And sequences if necessary.
+
+  // 14. If V is a Boolean value, then:
+  //   1. If types includes a boolean, then return the result of converting V
+  //      to boolean.
+  if (value.isBoolean()) {
+    if (UnionTypeTraitsT1::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType3<T1, T2, T3>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType3<T1, T2, T3>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType3<T1, T2, T3>(t3);
+      return;
+    }
+  }
+
+  // 15. If V is a Number value, then:
+  //   1. If types includes a numeric type, then return the result of converting
+  //      V to that numeric type.
+  if (value.isNumber()) {
+    if (UnionTypeTraitsT1::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType3<T1, T2, T3>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType3<T1, T2, T3>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType3<T1, T2, T3>(t3);
+      return;
+    }
+  }
+
+  // 16. If types includes a string type, then return the result of converting V
+  // to that type.
+  if (value.isString()) {
+    if (UnionTypeTraitsT1::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType3<T1, T2, T3>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType3<T1, T2, T3>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType3<T1, T2, T3>(t3);
+      return;
+    }
+  }
+
+  // 17. If types includes a numeric type, then return the result of converting
+  // V to that numeric type.
+  if (UnionTypeTraitsT1::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType3<T1, T2, T3>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType3<T1, T2, T3>(t2);
+    return;
+  }
+  if (UnionTypeTraitsT3::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t3);
+    *out_union = script::UnionType3<T1, T2, T3>(t3);
+    return;
+  }
+  // 18. If types includes a boolean, then return the result of converting V to
+  // boolean.
+  if (UnionTypeTraitsT1::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType3<T1, T2, T3>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType3<T1, T2, T3>(t2);
+    return;
+  }
+  if (UnionTypeTraitsT3::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t3);
+    *out_union = script::UnionType3<T1, T2, T3>(t3);
+    return;
+  }
+  // 19. Throw a TypeError.
+  exception_state->SetSimpleException(
+      ExceptionState::kTypeError, "Value is not a member of the union type.");
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void ToJSValue(JSContext* context,
+               const script::UnionType4<T1, T2, T3, T4>& in_union,
+               JS::MutableHandleValue out_value) {
+  if (in_union.template IsType<T1>()) {
+    ToJSValue(context, in_union.template AsType<T1>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T2>()) {
+    ToJSValue(context, in_union.template AsType<T2>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T3>()) {
+    ToJSValue(context, in_union.template AsType<T3>(), out_value);
+    return;
+  }
+  if (in_union.template IsType<T4>()) {
+    ToJSValue(context, in_union.template AsType<T4>(), out_value);
+    return;
+  }
+  NOTREACHED();
+  out_value.setUndefined();
+}
+
+template <typename T1, typename T2, typename T3, typename T4>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType4<T1, T2, T3, T4>* out_union) {
+  DCHECK_EQ(0, conversion_flags);
+  // JS -> IDL type conversion procedure described here:
+  // http://heycam.github.io/webidl/#es-union
+
+  // 1. If the union type includes a nullable type and V is null or undefined,
+  // then return the IDL value null.
+  if (value.isNull() || value.isUndefined()) {
+    // If the type was nullable or undefined, we should have caught that as a
+    // part of the base::optional<T> conversion.
+    NOTREACHED();
+    return;
+  }
+  // Typedef for readability.
+  typedef ::cobalt::script::internal::UnionTypeTraits<T1> UnionTypeTraitsT1;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T2> UnionTypeTraitsT2;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T3> UnionTypeTraitsT3;
+  typedef ::cobalt::script::internal::UnionTypeTraits<T4> UnionTypeTraitsT4;
+
+  // Forward declare all potential types
+  T1 t1;
+  T2 t2;
+  T3 t3;
+  T4 t4;
+
+  // 3.1 If types includes an interface type that V implements, then return the
+  //     IDL value that is a reference to the object V.
+  // 3.2 If types includes object, then return the IDL value that is a reference
+  //     to the object V.
+  //
+  // The specification doesn't dictate what should happen if V implements more
+  // than one of the interfaces. For example, if V implements interface B and
+  // interface B inherits from interface A, what happens if both A and B are
+  // union members? Blink doesn't seem to do anything special for this case.
+  // Just choose the first interface in the flattened members that matches.
+  if (value.isObject()) {
+    JS::RootedObject rooted_object(context);
+    bool success = JS_ValueToObject(context, value, rooted_object.address());
+    DCHECK(success);
+    MozjsGlobalObjectProxy* global_object_proxy =
+        static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+    const WrapperFactory* wrapper_factory =
+        global_object_proxy->wrapper_factory();
+    if (UnionTypeTraitsT1::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT1::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+      return;
+    }
+    if (UnionTypeTraitsT2::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT2::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+      return;
+    }
+    if (UnionTypeTraitsT3::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT3::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+      return;
+    }
+    if (UnionTypeTraitsT4::is_interface_type &&
+        wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT4::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t4);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+      return;
+    }
+  }
+
+  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
+  //       TypedArrayName, callback functions, dictionary, array type.
+  //       And sequences if necessary.
+
+  // 14. If V is a Boolean value, then:
+  //   1. If types includes a boolean, then return the result of converting V
+  //      to boolean.
+  if (value.isBoolean()) {
+    if (UnionTypeTraitsT1::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+      return;
+    }
+
+    if (UnionTypeTraitsT4::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t4);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+      return;
+    }
+  }
+
+  // 15. If V is a Number value, then:
+  //   1. If types includes a numeric type, then return the result of converting
+  //      V to that numeric type.
+  if (value.isNumber()) {
+    if (UnionTypeTraitsT1::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+      return;
+    }
+
+    if (UnionTypeTraitsT4::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t4);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+      return;
+    }
+  }
+
+  // 16. If types includes a string type, then return the result of converting V
+  // to that type.
+  if (value.isString()) {
+    if (UnionTypeTraitsT1::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t1);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+      return;
+    }
+
+    if (UnionTypeTraitsT2::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t2);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+      return;
+    }
+
+    if (UnionTypeTraitsT3::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t3);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+      return;
+    }
+
+    if (UnionTypeTraitsT4::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t4);
+      *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+      return;
+    }
+  }
+
+  // 17. If types includes a numeric type, then return the result of converting
+  // V to that numeric type.
+  if (UnionTypeTraitsT1::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+    return;
+  }
+  if (UnionTypeTraitsT3::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t3);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+    return;
+  }
+  if (UnionTypeTraitsT4::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t4);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+    return;
+  }
+  // 18. If types includes a boolean, then return the result of converting V to
+  // boolean.
+  if (UnionTypeTraitsT1::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t1);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t1);
+    return;
+  }
+  if (UnionTypeTraitsT2::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t2);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t2);
+    return;
+  }
+  if (UnionTypeTraitsT3::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t3);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t3);
+    return;
+  }
+  if (UnionTypeTraitsT4::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t4);
+    *out_union = script::UnionType4<T1, T2, T3, T4>(t4);
+    return;
+  }
+  // 19. Throw a TypeError.
+  exception_state->SetSimpleException(
+      ExceptionState::kTypeError, "Value is not a member of the union type.");
+}
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump b/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump
new file mode 100644
index 0000000..046f822
--- /dev/null
+++ b/src/cobalt/script/mozjs/union_type_conversion_impl.h.pump
@@ -0,0 +1,205 @@
+$$ This is a pump file for generating file templates.  Pump is a python
+$$ script that is part of the Google Test suite of utilities.  Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+$$ Maximum number of different member types in a union.
+$var MAX_MEMBERS = 4
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
+#define COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
+
+#include "cobalt/base/type_id.h"
+#include "cobalt/script/mozjs/mozjs_exception_state.h"
+#include "cobalt/script/mozjs/mozjs_global_object_proxy.h"
+#include "cobalt/script/mozjs/mozjs_object_handle.h"
+#include "cobalt/script/mozjs/mozjs_user_object_holder.h"
+#include "cobalt/script/mozjs/type_traits.h"
+#include "cobalt/script/union_type.h"
+
+// Conversion to/from JS::Value for IDL union types.
+
+namespace cobalt {
+namespace script {
+namespace mozjs {
+
+$range NUM_MEMBERS 2..MAX_MEMBERS
+$for NUM_MEMBERS [[
+
+$range TYPE 1..NUM_MEMBERS
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void ToJSValue(JSContext* context, const script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>& in_union, JS::MutableHandleValue out_value) {
+$for TYPE [[
+
+  if (in_union.template IsType<T$(TYPE)>()) {
+      ToJSValue(context, in_union.template AsType<T$(TYPE)>(), out_value);
+      return;
+  }
+]]
+
+  NOTREACHED();
+  out_value.setUndefined();
+}
+
+template <$for TYPE , [[typename T$(TYPE)]]>
+void FromJSValue(JSContext* context, JS::HandleValue value,
+                 int conversion_flags, ExceptionState* exception_state,
+                 script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>* out_union) {
+  DCHECK_EQ(0, conversion_flags);
+  // JS -> IDL type conversion procedure described here:
+  // http://heycam.github.io/webidl/#es-union
+
+  // 1. If the union type includes a nullable type and V is null or undefined,
+  // then return the IDL value null.
+  if (value.isNull() || value.isUndefined()) {
+    // If the type was nullable or undefined, we should have caught that as a
+    // part of the base::optional<T> conversion.
+    NOTREACHED();
+    return;
+  }
+  // Typedef for readability.
+
+$for TYPE [[
+  typedef ::cobalt::script::internal::UnionTypeTraits<T$(TYPE)> UnionTypeTraitsT$(TYPE);
+
+]]
+
+  // Forward declare all potential types
+
+$for TYPE [[
+  T$(TYPE) t$(TYPE);
+
+]]
+
+  // 3.1 If types includes an interface type that V implements, then return the
+  //     IDL value that is a reference to the object V.
+  // 3.2 If types includes object, then return the IDL value that is a reference
+  //     to the object V.
+  //
+  // The specification doesn't dictate what should happen if V implements more
+  // than one of the interfaces. For example, if V implements interface B and
+  // interface B inherits from interface A, what happens if both A and B are
+  // union members? Blink doesn't seem to do anything special for this case.
+  // Just choose the first interface in the flattened members that matches.
+  if (value.isObject()) {
+
+    JS::RootedObject rooted_object(context);
+    bool success = JS_ValueToObject(context, value, rooted_object.address());
+    DCHECK(success);
+    MozjsGlobalObjectProxy* global_object_proxy =
+        static_cast<MozjsGlobalObjectProxy*>(JS_GetContextPrivate(context));
+    const WrapperFactory* wrapper_factory =
+        global_object_proxy->wrapper_factory();
+
+$for TYPE [[
+    if (UnionTypeTraitsT$(TYPE)::is_interface_type
+        && wrapper_factory->DoesObjectImplementInterface(
+            rooted_object, UnionTypeTraitsT$(TYPE)::GetTypeID())) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+      return;
+    }
+
+]]
+  }
+
+  // TODO: Support Date, RegExp, DOMException, Error, ArrayBuffer, DataView,
+  //       TypedArrayName, callback functions, dictionary, array type.
+  //       And sequences if necessary.
+
+  // 14. If V is a Boolean value, then:
+  //   1. If types includes a boolean, then return the result of converting V
+  //      to boolean.
+  if (value.isBoolean()) {
+$for TYPE [[
+
+    if (UnionTypeTraitsT$(TYPE)::is_boolean_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+      return;
+    }
+
+]]
+  }
+
+  // 15. If V is a Number value, then:
+  //   1. If types includes a numeric type, then return the result of converting
+  //      V to that numeric type.
+  if (value.isNumber()) {
+$for TYPE [[
+
+    if (UnionTypeTraitsT$(TYPE)::is_numeric_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+      return;
+    }
+
+]]
+  }
+
+  // 16. If types includes a string type, then return the result of converting V
+  // to that type.
+  if (value.isString()) {
+$for TYPE [[
+
+    if (UnionTypeTraitsT$(TYPE)::is_string_type) {
+      FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+      *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+      return;
+    }
+
+]]
+  }
+
+  // 17. If types includes a numeric type, then return the result of converting
+  // V to that numeric type.
+$for TYPE [[
+
+  if (UnionTypeTraitsT$(TYPE)::is_numeric_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+    *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+    return;
+  }
+]]
+
+  // 18. If types includes a boolean, then return the result of converting V to
+  // boolean.
+$for TYPE [[
+
+  if (UnionTypeTraitsT$(TYPE)::is_boolean_type) {
+    FromJSValue(context, value, conversion_flags, exception_state, &t$(TYPE));
+    *out_union = script::UnionType$(NUM_MEMBERS)<$for TYPE , [[T$(TYPE)]]>(t$(TYPE));
+    return;
+  }
+]]
+
+  // 19. Throw a TypeError.
+  exception_state->SetSimpleException(
+      ExceptionState::kTypeError, "Value is not a member of the union type.");
+}
+
+]]  $$ for NUM_MEMBERS
+
+}  // namespace mozjs
+}  // namespace script
+}  // namespace cobalt
+
+#endif  // COBALT_SCRIPT_MOZJS_UNION_TYPE_CONVERSION_IMPL_H_
diff --git a/src/cobalt/script/mozjs/wrapper_factory.cc b/src/cobalt/script/mozjs/wrapper_factory.cc
index b5c4bad..72b2edb 100644
--- a/src/cobalt/script/mozjs/wrapper_factory.cc
+++ b/src/cobalt/script/mozjs/wrapper_factory.cc
@@ -20,37 +20,42 @@
 #include "base/lazy_instance.h"
 #include "cobalt/script/mozjs/mozjs_wrapper_handle.h"
 #include "cobalt/script/mozjs/wrapper_private.h"
+#include "third_party/mozjs/js/src/jsproxy.h"
 
 namespace cobalt {
 namespace script {
 namespace mozjs {
 
 void WrapperFactory::RegisterWrappableType(
-    base::TypeId wrappable_type, const CreateWrapperFunction& create_function) {
-  std::pair<CreateWrapperHashMap::iterator, bool> pib =
-      create_wrapper_functions_.insert(
-          std::make_pair(wrappable_type, create_function));
+    base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
+    const PrototypeClassFunction& class_function) {
+  std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib =
+      wrappable_type_functions_.insert(std::make_pair(
+          wrappable_type,
+          WrappableTypeFunctions(create_function, class_function)));
   DCHECK(pib.second)
       << "RegisterWrappableType registered for type more than once.";
 }
 
-JSObject* WrapperFactory::GetWrapper(
+JSObject* WrapperFactory::GetWrapperProxy(
     const scoped_refptr<Wrappable>& wrappable) const {
   if (!wrappable) {
     return NULL;
   }
 
-  JS::RootedObject wrapper(context_, MozjsWrapperHandle::GetJSObject(
-                                         GetCachedWrapper(wrappable.get())));
-  if (!wrapper) {
+  JS::RootedObject wrapper_proxy(
+      context_,
+      MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get())));
+  if (!wrapper_proxy) {
     scoped_ptr<Wrappable::WeakWrapperHandle> object_handle =
         CreateWrapper(wrappable);
     SetCachedWrapper(wrappable.get(), object_handle.Pass());
-    wrapper =
-        MozjsWrapperHandle::GetJSObject(GetCachedWrapper(wrappable.get()));
+    wrapper_proxy =
+        MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get()));
   }
-  DCHECK(wrapper);
-  return wrapper;
+  DCHECK(wrapper_proxy);
+  DCHECK(js::IsProxy(wrapper_proxy));
+  return wrapper_proxy;
 }
 
 bool WrapperFactory::IsWrapper(JS::HandleObject wrapper) const {
@@ -59,20 +64,44 @@
 
 scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
     const scoped_refptr<Wrappable>& wrappable) const {
-  CreateWrapperHashMap::const_iterator it =
-      create_wrapper_functions_.find(wrappable->GetWrappableType());
-  if (it == create_wrapper_functions_.end()) {
+  WrappableTypeFunctionsHashMap::const_iterator it =
+      wrappable_type_functions_.find(wrappable->GetWrappableType());
+  if (it == wrappable_type_functions_.end()) {
     NOTREACHED();
     return scoped_ptr<Wrappable::WeakWrapperHandle>();
   }
-  JS::RootedObject new_object(context_, it->second.Run(context_, wrappable));
+  JS::RootedObject new_proxy(
+      context_, it->second.create_wrapper.Run(context_, wrappable));
   WrapperPrivate* wrapper_private =
-      reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(new_object));
+      WrapperPrivate::GetFromProxyObject(context_, new_proxy);
   DCHECK(wrapper_private);
   return make_scoped_ptr<Wrappable::WeakWrapperHandle>(
       new MozjsWrapperHandle(wrapper_private));
 }
 
+bool WrapperFactory::DoesObjectImplementInterface(JSObject* object,
+                                                  base::TypeId type_id) const {
+  WrappableTypeFunctionsHashMap::const_iterator it =
+      wrappable_type_functions_.find(type_id);
+  if (it == wrappable_type_functions_.end()) {
+    NOTREACHED();
+    return false;
+  }
+  const JSClass* proto_class = it->second.prototype_class.Run(context_);
+  JS::RootedObject object_proto_object(context_);
+  bool success =
+      JS_GetPrototype(context_, object, object_proto_object.address());
+  bool equality = false;
+  while (!equality && success && object_proto_object) {
+    // Get the class of the prototype.
+    JSClass* object_proto_class = JS_GetClass(object_proto_object);
+    equality = (object_proto_class == proto_class);
+    // Get the prototype of the previous prototype.
+    success = JS_GetPrototype(context_, object_proto_object,
+                              object_proto_object.address());
+  }
+  return equality;
+}
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/wrapper_factory.h b/src/cobalt/script/mozjs/wrapper_factory.h
index cf54027..828bdac 100644
--- a/src/cobalt/script/mozjs/wrapper_factory.h
+++ b/src/cobalt/script/mozjs/wrapper_factory.h
@@ -37,25 +37,39 @@
   typedef base::Callback<JSObject*(JSContext*, const scoped_refptr<Wrappable>&)>
       CreateWrapperFunction;
 
+  // Callback to get JSClass* of prototype.
+  typedef base::Callback<const JSClass*(JSContext*)> PrototypeClassFunction;
+
   explicit WrapperFactory(JSContext* context) : context_(context) {}
   void RegisterWrappableType(base::TypeId wrappable_type,
-                             const CreateWrapperFunction& create_function);
+                             const CreateWrapperFunction& create_function,
+                             const PrototypeClassFunction& class_function);
 
-  // Gets the Wrapper object for this Wrappable. It may create a new Wrapper.
-  JSObject* GetWrapper(const scoped_refptr<Wrappable>& wrappable) const;
-
+  // Gets the Proxy for the Wrapper object for this Wrappable. It may create a
+  // new Wrapper and Proxy.
+  JSObject* GetWrapperProxy(const scoped_refptr<Wrappable>& wrappable) const;
   // Returns true if this JSObject is a Wrapper object.
   bool IsWrapper(JS::HandleObject wrapper) const;
 
+  bool DoesObjectImplementInterface(JSObject*, base::TypeId) const;
+
  private:
+  struct WrappableTypeFunctions {
+    CreateWrapperFunction create_wrapper;
+    PrototypeClassFunction prototype_class;
+    WrappableTypeFunctions(const CreateWrapperFunction& create_wrapper,
+                           const PrototypeClassFunction& prototype_class)
+        : create_wrapper(create_wrapper), prototype_class(prototype_class) {}
+  };
+
   scoped_ptr<Wrappable::WeakWrapperHandle> CreateWrapper(
       const scoped_refptr<Wrappable>& wrappable) const;
 
-  typedef base::hash_map<base::TypeId, CreateWrapperFunction>
-      CreateWrapperHashMap;
+  typedef base::hash_map<base::TypeId, WrappableTypeFunctions>
+      WrappableTypeFunctionsHashMap;
 
   JSContext* context_;
-  CreateWrapperHashMap create_wrapper_functions_;
+  WrappableTypeFunctionsHashMap wrappable_type_functions_;
 };
 
 }  // namespace mozjs
diff --git a/src/cobalt/script/mozjs/wrapper_private.cc b/src/cobalt/script/mozjs/wrapper_private.cc
index dad78c9..b7b3443 100644
--- a/src/cobalt/script/mozjs/wrapper_private.cc
+++ b/src/cobalt/script/mozjs/wrapper_private.cc
@@ -17,6 +17,7 @@
 #include "cobalt/script/mozjs/wrapper_private.h"
 
 #include "third_party/mozjs/js/src/jsapi.h"
+#include "third_party/mozjs/js/src/jsproxy.h"
 
 namespace cobalt {
 namespace script {
@@ -38,26 +39,55 @@
 }
 
 // static
-void WrapperPrivate::AddPrivateData(JS::HandleObject wrapper,
+void WrapperPrivate::AddPrivateData(JS::HandleObject wrapper_proxy,
                                     const scoped_refptr<Wrappable>& wrappable) {
-  WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper);
-  JS_SetPrivate(wrapper, private_data);
-  DCHECK_EQ(JS_GetPrivate(wrapper), private_data);
+  DCHECK(js::IsProxy(wrapper_proxy));
+  WrapperPrivate* private_data = new WrapperPrivate(wrappable, wrapper_proxy);
+  JSObject* target_object = js::GetProxyTargetObject(wrapper_proxy);
+  JS_SetPrivate(target_object, private_data);
+  DCHECK_EQ(JS_GetPrivate(target_object), private_data);
 }
 
 // static
 WrapperPrivate* WrapperPrivate::GetFromWrappable(
     const scoped_refptr<Wrappable>& wrappable, JSContext* context,
     WrapperFactory* wrapper_factory) {
-  JS::RootedObject wrapper(context, wrapper_factory->GetWrapper(wrappable));
-  WrapperPrivate* private_data =
-      static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper));
+  JS::RootedObject wrapper_proxy(context,
+                                 wrapper_factory->GetWrapperProxy(wrappable));
+  WrapperPrivate* private_data = GetFromProxyObject(context, wrapper_proxy);
   DCHECK(private_data);
   DCHECK_EQ(private_data->wrappable_, wrappable);
   return private_data;
 }
 
 // static
+WrapperPrivate* WrapperPrivate::GetFromWrapperObject(JS::HandleObject wrapper) {
+  DCHECK(!js::IsProxy(wrapper));
+  WrapperPrivate* private_data =
+      static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper));
+  DCHECK(private_data);
+  return private_data;
+}
+
+// static
+WrapperPrivate* WrapperPrivate::GetFromProxyObject(
+    JSContext* context, JS::HandleObject proxy_object) {
+  DCHECK(js::IsProxy(proxy_object));
+  JS::RootedObject target(context, js::GetProxyTargetObject(proxy_object));
+  return GetFromWrapperObject(target);
+}
+
+// static
+WrapperPrivate* WrapperPrivate::GetFromObject(JSContext* context,
+                                              JS::HandleObject object) {
+  if (js::IsProxy(object)) {
+    return GetFromProxyObject(context, object);
+  } else {
+    return GetFromWrapperObject(object);
+  }
+}
+
+// static
 void WrapperPrivate::Finalizer(JSFreeOp* /* free_op */, JSObject* object) {
   WrapperPrivate* wrapper_private =
       reinterpret_cast<WrapperPrivate*>(JS_GetPrivate(object));
@@ -78,6 +108,12 @@
   }
 }
 
+WrapperPrivate::WrapperPrivate(const scoped_refptr<Wrappable>& wrappable,
+                               JS::HandleObject wrapper_proxy)
+    : wrappable_(wrappable), wrapper_proxy_(wrapper_proxy) {
+  DCHECK(js::IsProxy(wrapper_proxy));
+}
+
 }  // namespace mozjs
 }  // namespace script
 }  // namespace cobalt
diff --git a/src/cobalt/script/mozjs/wrapper_private.h b/src/cobalt/script/mozjs/wrapper_private.h
index 6352c3a..9bb4219 100644
--- a/src/cobalt/script/mozjs/wrapper_private.h
+++ b/src/cobalt/script/mozjs/wrapper_private.h
@@ -34,8 +34,12 @@
 // must be destroyed when its JSObject is garbage collected.
 class WrapperPrivate : public base::SupportsWeakPtr<WrapperPrivate> {
  public:
-  const scoped_refptr<Wrappable>& wrappable() const { return wrappable_; }
-  JSObject* js_object() const { return wrapper_; }
+  template <typename T>
+  scoped_refptr<T> wrappable() const {
+    return base::polymorphic_downcast<T*>(wrappable_.get());
+  }
+
+  JSObject* js_object_proxy() const { return wrapper_proxy_; }
 
   // Add/Remove a reference to the object. The object will be visited during
   // garbage collection.
@@ -43,7 +47,7 @@
   void RemoveReferencedObject(JS::HandleObject referee);
 
   // Create a new WrapperPrivate instance and associate it with the wrapper.
-  static void AddPrivateData(JS::HandleObject wrapper,
+  static void AddPrivateData(JS::HandleObject wrapper_proxy,
                              const scoped_refptr<Wrappable>& wrappable);
 
   // Get the WrapperPrivate associated with the given Wrappable. A new JSObject
@@ -52,13 +56,17 @@
       const scoped_refptr<Wrappable>& wrappable, JSContext* context,
       WrapperFactory* wrapper_factory);
 
-  template <typename T>
-  static T* GetWrappable(JS::HandleObject wrapper) {
-    WrapperPrivate* private_data =
-        static_cast<WrapperPrivate*>(JS_GetPrivate(wrapper));
-    DCHECK(private_data);
-    return base::polymorphic_downcast<T*>(private_data->wrappable_.get());
-  }
+  // Get the WrapperPrivate instance associated with this Wrapper object.
+  static WrapperPrivate* GetFromWrapperObject(JS::HandleObject object);
+
+  // Get the WrapperPrivate instance associated with the target of this proxy.
+  static WrapperPrivate* GetFromProxyObject(JSContext* context,
+                                            JS::HandleObject proxy_object);
+
+  // Get the WrapperPrivate instance associated with the object, which may
+  // be a proxy or a proxy target.
+  static WrapperPrivate* GetFromObject(JSContext* context,
+                                       JS::HandleObject object);
 
   // Called when the wrapper object is about to be deleted by the GC.
   static void Finalizer(JSFreeOp* /* free_op */, JSObject* object);
@@ -69,11 +77,10 @@
  private:
   typedef ScopedVector<JS::Heap<JSObject*> > ReferencedObjectVector;
   WrapperPrivate(const scoped_refptr<Wrappable>& wrappable,
-                 JS::HandleObject wrapper)
-      : wrappable_(wrappable), wrapper_(wrapper) {}
+                 JS::HandleObject wrapper_proxy);
 
   scoped_refptr<Wrappable> wrappable_;
-  JS::Heap<JSObject*> wrapper_;
+  JS::Heap<JSObject*> wrapper_proxy_;
   ReferencedObjectVector referenced_objects_;
 };
 
diff --git a/src/cobalt/storage/storage.gyp b/src/cobalt/storage/storage.gyp
index 25820d7..599f95a 100644
--- a/src/cobalt/storage/storage.gyp
+++ b/src/cobalt/storage/storage.gyp
@@ -89,7 +89,7 @@
       'variables': {
         'executable_name': 'storage_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/storage/storage_manager_test.cc b/src/cobalt/storage/storage_manager_test.cc
index 623aa7f..fbd0c9c 100644
--- a/src/cobalt/storage/storage_manager_test.cc
+++ b/src/cobalt/storage/storage_manager_test.cc
@@ -50,7 +50,7 @@
   CallbackWaiter() : was_called_event_(true, false) {}
   virtual ~CallbackWaiter() {}
   bool TimedWait() {
-    return was_called_event_.TimedWait(base::TimeDelta::FromMilliseconds(500));
+    return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5));
   }
 
  protected:
diff --git a/src/cobalt/system_window/starboard/system_window.cc b/src/cobalt/system_window/starboard/system_window.cc
index 0494e53..111cf8b 100644
--- a/src/cobalt/system_window/starboard/system_window.cc
+++ b/src/cobalt/system_window/starboard/system_window.cc
@@ -19,12 +19,19 @@
 #include "cobalt/base/event_dispatcher.h"
 #include "cobalt/system_window/keyboard_event.h"
 #include "cobalt/system_window/starboard/system_window.h"
+#include "starboard/system.h"
 
 namespace cobalt {
 namespace system_window {
 
 namespace {
 SystemWindowStarboard* g_the_window = NULL;
+
+// Unbound callback handler for SbWindowShowDialog.
+void StarboardDialogCallback(SbSystemPlatformErrorResponse response) {
+  DCHECK(g_the_window);
+  g_the_window->HandleDialogClose(response);
+}
 }  // namespace
 
 SystemWindowStarboard::SystemWindowStarboard(
@@ -78,6 +85,60 @@
   }
 }
 
+void OnDialogClose(SbSystemPlatformErrorResponse response, void* user_data) {
+  DCHECK(user_data);
+  SystemWindowStarboard* system_window =
+      static_cast<SystemWindowStarboard*>(user_data);
+  system_window->HandleDialogClose(response);
+}
+
+void SystemWindowStarboard::ShowDialog(
+    const SystemWindow::DialogOptions& options) {
+  SbSystemPlatformErrorType error_type;
+  switch (options.message_code) {
+    case kDialogConnectionError:
+      error_type = kSbSystemPlatformErrorTypeConnectionError;
+      break;
+    case kDialogUserSignedOut:
+      error_type = kSbSystemPlatformErrorTypeUserSignedOut;
+      break;
+    case kDialogUserAgeRestricted:
+      error_type = kSbSystemPlatformErrorTypeUserAgeRestricted;
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+
+  SbSystemPlatformError handle =
+      SbSystemRaisePlatformError(error_type, OnDialogClose, this);
+  if (SbSystemPlatformErrorIsValid(handle)) {
+    current_dialog_callback_ = options.callback;
+  } else {
+    DLOG(WARNING) << "Failed to notify user of error: "
+                  << options.message_code;
+  }
+}
+
+void SystemWindowStarboard::HandleDialogClose(
+    SbSystemPlatformErrorResponse response) {
+  DCHECK(!current_dialog_callback_.is_null());
+  switch (response) {
+    case kSbSystemPlatformErrorResponsePositive:
+      current_dialog_callback_.Run(kDialogPositiveResponse);
+      break;
+    case kSbSystemPlatformErrorResponseNegative:
+      current_dialog_callback_.Run(kDialogNegativeResponse);
+      break;
+    case kSbSystemPlatformErrorResponseCancel:
+      current_dialog_callback_.Run(kDialogCancelResponse);
+      break;
+    default:
+      DLOG(WARNING) << "Unrecognized dialog response: " << response;
+      break;
+  }
+}
+
 scoped_ptr<SystemWindow> CreateSystemWindow(
     base::EventDispatcher* event_dispatcher, const math::Size& window_size) {
   return scoped_ptr<SystemWindow>(
diff --git a/src/cobalt/system_window/starboard/system_window.h b/src/cobalt/system_window/starboard/system_window.h
index 072c481..efc6caa 100644
--- a/src/cobalt/system_window/starboard/system_window.h
+++ b/src/cobalt/system_window/starboard/system_window.h
@@ -23,7 +23,7 @@
 #include "starboard/event.h"
 #include "starboard/input.h"
 #include "starboard/key.h"
-#include "starboard/window.h"
+#include "starboard/system.h"
 
 namespace cobalt {
 namespace system_window {
@@ -43,6 +43,12 @@
   // Handles a single Starboard input event, dispatching any appropriate events.
   void HandleInputEvent(const SbInputData& data);
 
+  // Raises a system dialog.
+  void ShowDialog(const SystemWindow::DialogOptions& options) OVERRIDE;
+
+  // Called when the user closes the dialog.
+  void HandleDialogClose(SbSystemPlatformErrorResponse response);
+
  private:
   void UpdateModifiers(SbKey key, bool pressed);
   KeyboardEvent::Modifiers GetModifiers();
@@ -50,6 +56,9 @@
   SbWindow window_;
 
   bool key_down_;
+
+  // The current dialog callback. Only one dialog may be open at a time.
+  DialogCallback current_dialog_callback_;
 };
 
 // The Starboard Event handler SbHandleEvent should call this function on
diff --git a/src/cobalt/system_window/system_window.h b/src/cobalt/system_window/system_window.h
index 272c5c9..4054bc0 100644
--- a/src/cobalt/system_window/system_window.h
+++ b/src/cobalt/system_window/system_window.h
@@ -46,21 +46,20 @@
   // Type of callback to run when user closes a dialog.
   typedef base::Callback<void(DialogResponse response)> DialogCallback;
 
-  // Type to indicate dialog severity. May be used by the platform-specific
-  // implementation to control aspects of dialog presentation.
-  enum DialogSeverity { kDialogInfo, kDialogWarning, kDialogError };
+  // Enumeration of possible message codes for a dialog.
+  enum DialogMessageCode {
+    kDialogConnectionError,
+    kDialogUserSignedOut,
+    kDialogUserAgeRestricted
+  };
 
   // Options structure for dialog creation. It is expected that each platform
   // will implement a modal dialog with possible support for:
-  // A text message.
-  // An indication of severity: info, warning or error.
-  // 1-3 buttons, where usually 1 = OK, 2 = Yes/No, 3 = Yes/No/Cancel.
+  // A message code specifying the text to be displayed, which should be
+  // localized according to the platform.
   // A callback indicating the user's response: positive, negative or cancel.
   struct DialogOptions {
-    DialogOptions() : severity(kDialogInfo), num_buttons(1) {}
-    DialogSeverity severity;
-    int num_buttons;
-    std::string message;
+    DialogMessageCode message_code;
     DialogCallback callback;
   };
 
diff --git a/src/cobalt/system_window/system_window_common.cc b/src/cobalt/system_window/system_window_common.cc
index 0a2ba8e..50ae183 100644
--- a/src/cobalt/system_window/system_window_common.cc
+++ b/src/cobalt/system_window/system_window_common.cc
@@ -25,7 +25,7 @@
 
 void SystemWindow::ShowDialog(const SystemWindow::DialogOptions& options) {
   NOTIMPLEMENTED() << "System dialog not implemented on this platform";
-  DLOG(INFO) << "Message: " << options.message;
+  DLOG(INFO) << "Message code: " << options.message_code;
 }
 
 }  // namespace system_window
diff --git a/src/cobalt/trace_event/trace_event.gyp b/src/cobalt/trace_event/trace_event.gyp
index 1b756f6..75d5c82 100644
--- a/src/cobalt/trace_event/trace_event.gyp
+++ b/src/cobalt/trace_event/trace_event.gyp
@@ -56,7 +56,7 @@
       'variables': {
         'executable_name': 'trace_event_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
@@ -108,7 +108,7 @@
       'variables': {
         'executable_name': 'sample_benchmark',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/web_animations/web_animations.gyp b/src/cobalt/web_animations/web_animations.gyp
index 5be6176..e4544ac 100644
--- a/src/cobalt/web_animations/web_animations.gyp
+++ b/src/cobalt/web_animations/web_animations.gyp
@@ -72,7 +72,7 @@
       'variables': {
         'executable_name': 'web_animations_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/cobalt/webdriver/webdriver.gyp b/src/cobalt/webdriver/webdriver.gyp
index 62e974f..558a0ee 100644
--- a/src/cobalt/webdriver/webdriver.gyp
+++ b/src/cobalt/webdriver/webdriver.gyp
@@ -131,7 +131,7 @@
       'variables': {
         'executable_name': 'webdriver_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
diff --git a/src/cobalt/xhr/xhr.gyp b/src/cobalt/xhr/xhr.gyp
index 8621405..06c24c5 100644
--- a/src/cobalt/xhr/xhr.gyp
+++ b/src/cobalt/xhr/xhr.gyp
@@ -58,7 +58,7 @@
       'variables': {
         'executable_name': 'xhr_test',
       },
-      'includes': [ '../build/deploy.gypi' ],
+      'includes': [ '../../starboard/build/deploy.gypi' ],
     },
 
     {
diff --git a/src/crypto/crypto.gyp b/src/crypto/crypto.gyp
index f83e290..2b37a30 100644
--- a/src/crypto/crypto.gyp
+++ b/src/crypto/crypto.gyp
@@ -389,7 +389,7 @@
           'variables': {
             'executable_name': 'crypto_unittests',
           },
-          'includes': [ '../cobalt/build/deploy.gypi' ],
+          'includes': [ '../starboard/build/deploy.gypi' ],
         },
       ],
     }],
diff --git a/src/glimp/gles/context.cc b/src/glimp/gles/context.cc
index a6577ac..a104230 100644
--- a/src/glimp/gles/context.cc
+++ b/src/glimp/gles/context.cc
@@ -1208,13 +1208,17 @@
 //   https://www.khronos.org/opengles/sdk/docs/man/xhtml/glTexImage2D.xml
 // Note that glimp may not support all possible formats described above.
 PixelFormat PixelFormatFromGLTypeAndFormat(GLenum format, GLenum type) {
-  if (type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
-    return kPixelFormatRGBA8;
-  } else if (type == GL_UNSIGNED_BYTE && format == GL_ALPHA) {
-    return kPixelFormatA8;
-  } else {
-    return kPixelFormatInvalid;
+  if (type == GL_UNSIGNED_BYTE) {
+    switch (format) {
+      case GL_RGBA:
+        return kPixelFormatRGBA8;
+      case GL_ALPHA:
+        return kPixelFormatA8;
+      case GL_LUMINANCE_ALPHA:
+        return kPixelFormatBA8;
+    }
   }
+  return kPixelFormatInvalid;
 }
 
 }  // namespace
diff --git a/src/glimp/gles/convert_pixel_data.cc b/src/glimp/gles/convert_pixel_data.cc
index 36249eb..7609baa 100644
--- a/src/glimp/gles/convert_pixel_data.cc
+++ b/src/glimp/gles/convert_pixel_data.cc
@@ -59,10 +59,14 @@
                         const uint8_t* source,
                         int num_pixels) {
   for (int i = 0; i < num_pixels; ++i) {
-    destination[0] = channel_0_source == -1 ? 0 : source[channel_0_source];
-    destination[1] = channel_1_source == -1 ? 0 : source[channel_1_source];
-    destination[2] = channel_2_source == -1 ? 0 : source[channel_2_source];
-    destination[3] = channel_3_source == -1 ? 0 : source[channel_3_source];
+    uint8_t channel_0 = channel_0_source == -1 ? 0 : source[channel_0_source];
+    uint8_t channel_1 = channel_1_source == -1 ? 0 : source[channel_1_source];
+    uint8_t channel_2 = channel_2_source == -1 ? 0 : source[channel_2_source];
+    uint8_t channel_3 = channel_3_source == -1 ? 0 : source[channel_3_source];
+    destination[0] = channel_0;
+    destination[1] = channel_1;
+    destination[2] = channel_2;
+    destination[3] = channel_3;
 
     destination += 4;
     source += source_bytes_per_pixel;
@@ -81,6 +85,9 @@
   } else if (destination_format == kPixelFormatRGBA8 &&
       source_format == kPixelFormatARGB8) {
     return &RemapPixelChannels<1, 2, 3, 0>;
+  } else if (destination_format == kPixelFormatRGBA8 &&
+             source_format == kPixelFormatBGRA8) {
+    return &RemapPixelChannels<2, 1, 0, 3>;
   }
 
   // Only what is currently needed by dependent libraries is supported, so
@@ -91,6 +98,36 @@
 
 }  // namespace
 
+void ConvertPixelDataInplace(uint8_t* pixels,
+                             int pitch_in_bytes,
+                             PixelFormat destination_format,
+                             PixelFormat source_format,
+                             int width,
+                             int height) {
+  if (destination_format == source_format) {
+    return;
+  }
+  SB_DCHECK(BytesPerPixel(destination_format) == BytesPerPixel(source_format));
+  // The destination format is different from the source format, so we must
+  // perform a conversion between pixels.
+
+  // First select the function that will reformat the pixels, based on
+  // the destination and source pixel formats.
+  ConvertRowFunction convert_row_function =
+      SelectConvertRowFunction(destination_format, source_format);
+  SB_DCHECK(convert_row_function)
+      << "The requested pixel conversion is not yet implemented.";
+
+  // Now, iterate through each row running the selected conversion function on
+  // each one.
+  uint8_t* pixel_row = pixels;
+  for (int row = 0; row < height; ++row) {
+    convert_row_function(BytesPerPixel(source_format), pixel_row, pixel_row,
+                         width);
+    pixel_row += pitch_in_bytes;
+  }
+}
+
 void ConvertPixelData(uint8_t* destination,
                       int destination_pitch_in_bytes,
                       PixelFormat destination_format,
diff --git a/src/glimp/gles/convert_pixel_data.h b/src/glimp/gles/convert_pixel_data.h
index 8c36212..c11721b 100644
--- a/src/glimp/gles/convert_pixel_data.h
+++ b/src/glimp/gles/convert_pixel_data.h
@@ -27,6 +27,15 @@
   kPixelDataBigEndian,
 };
 
+// Converts pixel data in pixel buffer from the source format into the
+// destination format, swizzeling the pixel color components if necessary.
+void ConvertPixelDataInplace(uint8_t* pixels,
+                             int pitch_in_bytes,
+                             PixelFormat destination_format,
+                             PixelFormat source_format,
+                             int width,
+                             int height);
+
 // Copies pixel data from the source buffer and format into the destination
 // buffer and format, swizzeling the pixel color components if necessary.
 void ConvertPixelData(uint8_t* destination,
diff --git a/src/glimp/gles/pixel_format.cc b/src/glimp/gles/pixel_format.cc
index 57bfebe..5c0f76b 100644
--- a/src/glimp/gles/pixel_format.cc
+++ b/src/glimp/gles/pixel_format.cc
@@ -27,12 +27,15 @@
     4,  // kPixelFormatARGB8
     4,  // kPixelFormatBGRA8
     2,  // kPixelFormatRGB565
+    2,  // kPixelFormatBA8
     1,  // kPixelFormatA8
 };
 
 }  // namespace
 
 int BytesPerPixel(PixelFormat format) {
+  SB_COMPILE_ASSERT(SB_ARRAY_SIZE(kBytesPerPixel) == kPixelFormatNumFormats,
+                    kBytesPerPixel_has_entries_for_each_enum_PixelFormat);
   return kBytesPerPixel[format];
 }
 
diff --git a/src/glimp/gles/pixel_format.h b/src/glimp/gles/pixel_format.h
index dcc597d..7268a75 100644
--- a/src/glimp/gles/pixel_format.h
+++ b/src/glimp/gles/pixel_format.h
@@ -31,8 +31,10 @@
   kPixelFormatARGB8,
   kPixelFormatBGRA8,
   kPixelFormatRGB565,
+  kPixelFormatBA8,
   kPixelFormatA8,
   kPixelFormatInvalid,
+  kPixelFormatNumFormats = kPixelFormatInvalid
 };
 
 // Returns the number of bytes per pixel for a given PixelFormat.
diff --git a/src/glimp/shaders/generate_glsl_shader_map.py b/src/glimp/shaders/generate_glsl_shader_map.py
index b024b5c..2ce1841 100644
--- a/src/glimp/shaders/generate_glsl_shader_map.py
+++ b/src/glimp/shaders/generate_glsl_shader_map.py
@@ -107,13 +107,40 @@
   for k, v in hash_to_shader_map.iteritems():
     input_file_variable_name = GetBasename(v)
     generate_map_function_string += (
-        '  (*out_map)[%d] = ShaderData(%s, sizeof(%s));\n' %
+        '  (*out_map)[%uU] = ShaderData(%s, sizeof(%s));\n' %
         (k, input_file_variable_name, input_file_variable_name))
 
-  generate_map_function_string += '}\n\n'
+  generate_map_function_string += '}'
   return generate_map_function_string
 
 
+
+def GetShaderNameFunctionString(hash_to_shader_map):
+  """Generate C++ code to retrieve the shader name from a GLSL hash.
+
+  Args:
+    hash_to_shader_map:
+      A dictionary where the keys are hashes and the values are
+      platform-specific shader filenames.
+  Returns:
+    A string of C++ code that defines a function that returns a string with the
+    corresponding shader name for the GLSL hash value passed as a parameter.
+  """
+
+  get_shader_name_function_string = (
+      'inline const char *GetShaderName(uint32_t hash_value) {\n'
+      '  switch(hash_value) {\n')
+
+  for k, v in hash_to_shader_map.iteritems():
+    input_file_variable_name = GetBasename(v)
+    get_shader_name_function_string += (
+        '    case %uU: return \"%s\";\n' %
+        (k, input_file_variable_name))
+
+  get_shader_name_function_string += '  }\n  return NULL;\n}'
+  return get_shader_name_function_string
+
+
 HEADER_FILE_TEMPLATE = """
 // Copyright 2016 Google Inc.  All Rights Reserved.
 // This file is generated (by glimp/shaders/generate_glsl_shader_map.py).
@@ -129,6 +156,11 @@
 
 {data_definitions}
 {generate_map_function}
+
+#if !defined(NDEBUG)
+{shader_name_function}
+#endif
+
 }}  // namespace shaders
 }}  // namespace glimp
 
@@ -153,7 +185,9 @@
             data_definitions = GetHeaderDataDefinitionString(
                                    hash_to_shader_map.values()),
             generate_map_function = GetGenerateMapFunctionString(
-                                        hash_to_shader_map)))
+                                        hash_to_shader_map),
+            shader_name_function = GetShaderNameFunctionString(
+                                       hash_to_shader_map)))
 
 
 def AssociateGLSLFilesWithPlatformFiles(all_shaders):
diff --git a/src/media/audio/null_audio_streamer.cc b/src/media/audio/null_audio_streamer.cc
index 2e3468a..0937b17 100644
--- a/src/media/audio/null_audio_streamer.cc
+++ b/src/media/audio/null_audio_streamer.cc
@@ -41,7 +41,7 @@
 ShellAudioStreamer::Config NullAudioStreamer::GetConfig() const {
   // Reasonable looking settings.
   const uint32 initial_rebuffering_frames_per_channel =
-      mp4::AAC::kSamplesPerFrame * 32;
+      mp4::AAC::kFramesPerAccessUnit * 32;
   const uint32 sink_buffer_size_in_frames_per_channel =
       initial_rebuffering_frames_per_channel * 8;
   const uint32 max_hardware_channels = 2;
diff --git a/src/media/audio/shell_audio_sink.cc b/src/media/audio/shell_audio_sink.cc
index be1a8d9..e46d3f7 100644
--- a/src/media/audio/shell_audio_sink.cc
+++ b/src/media/audio/shell_audio_sink.cc
@@ -227,7 +227,7 @@
   // Number of ms of buffered playback remaining
   uint32_t buffered_time =
       (*total_frames * 1000 / audio_parameters_.sample_rate());
-  if (free_frames >= mp4::AAC::kSamplesPerFrame) {
+  if (free_frames >= mp4::AAC::kFramesPerAccessUnit) {
     SetupRenderAudioBus();
 
     int frames_rendered =
@@ -238,7 +238,7 @@
       // +ve value indicates number of samples in a successful read
       // TODO: We cannot guarantee this on platforms that use a resampler. Check
       // if it is possible to move the resample into the streamer.
-      // DCHECK_EQ(frames_rendered, mp4::AAC::kSamplesPerFrame);
+      // DCHECK_EQ(frames_rendered, mp4::AAC::kFramesPerAccessUnit);
       render_frame_cursor_ += frames_rendered;
       *total_frames += frames_rendered;
       free_frames -= frames_rendered;
@@ -247,7 +247,7 @@
     render_callback_->Render(NULL, buffered_time);
   }
 
-  bool buffer_full = free_frames < mp4::AAC::kSamplesPerFrame;
+  bool buffer_full = free_frames < mp4::AAC::kFramesPerAccessUnit;
   DCHECK_LE(*total_frames,
             static_cast<uint32>(std::numeric_limits<int32>::max()));
   bool rebuffer_threshold_reached =
@@ -266,7 +266,7 @@
 #endif  // #if defined(OS_STARBOARD)
 
 #if defined(MEDIA_UNDERFLOW_DETECTED_BY_AUDIO_SINK)
-  const size_t kUnderflowThreshold = mp4::AAC::kSamplesPerFrame / 2;
+  const size_t kUnderflowThreshold = mp4::AAC::kFramesPerAccessUnit / 2;
   if (*total_frames < kUnderflowThreshold) {
     if (!rebuffering_) {
       rebuffering_ = true;
@@ -313,7 +313,7 @@
   // check for buffer wraparound, hopefully rare
   int render_frame_position =
       render_frame_cursor_ % settings_.per_channel_frames(audio_bus_.get());
-  int requested_frames = mp4::AAC::kSamplesPerFrame;
+  int requested_frames = mp4::AAC::kFramesPerAccessUnit;
   if (render_frame_position + requested_frames >
       settings_.per_channel_frames(audio_bus_.get())) {
     requested_frames =
diff --git a/src/media/audio/shell_audio_sink_unittest.cc b/src/media/audio/shell_audio_sink_unittest.cc
index 6860ffe..60995c1 100644
--- a/src/media/audio/shell_audio_sink_unittest.cc
+++ b/src/media/audio/shell_audio_sink_unittest.cc
@@ -33,7 +33,7 @@
 using namespace testing;
 
 const uint32 kMaxHardwareChannelsStereo = 2;
-const size_t kSamplesPerFrame = media::mp4::AAC::kSamplesPerFrame;
+const size_t kFramesPerAccessUnit = media::mp4::AAC::kFramesPerAccessUnit;
 
 bool operator==(const media::AudioParameters& params1,
                 const media::AudioParameters& params2) {
@@ -483,8 +483,8 @@
     for (int i = 0; i < 10; ++i) {
       // Try to get 1024 frames but don't give it any data
       EXPECT_CALL(render_callback_, Render(_, _))
-          .WillOnce(
-              VerifyAudioBusFrameCount(config, init_params, kSamplesPerFrame));
+          .WillOnce(VerifyAudioBusFrameCount(config, init_params,
+                                             kFramesPerAccessUnit));
       EXPECT_FALSE(sink_->PullFrames(NULL, NULL));
 
       // Ok, now give it 1024 frames
@@ -494,8 +494,8 @@
 
       // Try to get another 1024 frames but don't give it any data
       EXPECT_CALL(render_callback_, Render(_, _))
-          .WillOnce(
-              VerifyAudioBusFrameCount(config, init_params, kSamplesPerFrame));
+          .WillOnce(VerifyAudioBusFrameCount(config, init_params,
+                                             kFramesPerAccessUnit));
       EXPECT_FALSE(sink_->PullFrames(NULL, NULL));
 
       // Ok, now give it 480 frames
diff --git a/src/media/audio/shell_audio_streamer.h b/src/media/audio/shell_audio_streamer.h
index b6caca7..ca529b3 100644
--- a/src/media/audio/shell_audio_streamer.h
+++ b/src/media/audio/shell_audio_streamer.h
@@ -91,11 +91,13 @@
           max_hardware_channels_(max_hardware_channels),
           bytes_per_sample_(bytes_per_sample),
           native_output_sample_rate_(native_output_sample_rate) {
-      const size_t kSamplesPerFrame = mp4::AAC::kSamplesPerFrame;
+      const size_t kFramesPerAccessUnit = mp4::AAC::kFramesPerAccessUnit;
       DCHECK_LE(initial_rebuffering_frames_per_channel,
                 sink_buffer_size_in_frames_per_channel);
-      DCHECK_EQ(initial_rebuffering_frames_per_channel % kSamplesPerFrame, 0);
-      DCHECK_EQ(sink_buffer_size_in_frames_per_channel % kSamplesPerFrame, 0);
+      DCHECK_EQ(initial_rebuffering_frames_per_channel % kFramesPerAccessUnit,
+                0);
+      DCHECK_EQ(sink_buffer_size_in_frames_per_channel % kFramesPerAccessUnit,
+                0);
     }
 
     bool interleaved() const {
diff --git a/src/media/audio/shell_audio_streamer_linux.cc b/src/media/audio/shell_audio_streamer_linux.cc
index 7852ec7..cd35b97 100644
--- a/src/media/audio/shell_audio_streamer_linux.cc
+++ b/src/media/audio/shell_audio_streamer_linux.cc
@@ -58,7 +58,7 @@
 
 ShellAudioStreamer::Config ShellAudioStreamerLinux::GetConfig() const {
   const uint32 initial_rebuffering_frames_per_channel =
-      mp4::AAC::kSamplesPerFrame * 32;
+      mp4::AAC::kFramesPerAccessUnit * 32;
   const uint32 sink_buffer_size_in_frames_per_channel =
       initial_rebuffering_frames_per_channel * 8;
   const uint32 max_hardware_channels = 2;
diff --git a/src/media/base/decoder_buffer_pool.h b/src/media/base/decoder_buffer_pool.h
index f278f39..2b2636b 100644
--- a/src/media/base/decoder_buffer_pool.h
+++ b/src/media/base/decoder_buffer_pool.h
@@ -35,7 +35,7 @@
  public:
   static const uint32 kMaxAudioChannels = 8;  // We support 7.1 at most.
   static const uint32 kMaxSamplesPerBuffer =
-      mp4::AAC::kSamplesPerFrame * kMaxAudioChannels;
+      mp4::AAC::kFramesPerAccessUnit * kMaxAudioChannels;
   static const size_t kBufferCount = 48;
 
   DecoderBufferPool(uint32 sample_size_in_bytes);
diff --git a/src/media/base/shell_video_data_allocator.cc b/src/media/base/shell_video_data_allocator.cc
index 8e24adb..e47e518 100644
--- a/src/media/base/shell_video_data_allocator.cc
+++ b/src/media/base/shell_video_data_allocator.cc
@@ -22,15 +22,16 @@
 
 ShellVideoDataAllocator::YV12Param::YV12Param(int decoded_width,
                                               int decoded_height,
-                                              const gfx::Rect& visible_rect)
+                                              const gfx::Rect& visible_rect,
+                                              uint8* data)
     : decoded_width_(decoded_width),
       decoded_height_(decoded_height),
       visible_rect_(visible_rect),
-      y_pitch_(0),
-      uv_pitch_(0),
-      y_data_(NULL),
-      u_data_(NULL),
-      v_data_(NULL) {}
+      y_pitch_(decoded_width),
+      uv_pitch_(decoded_width / 2),
+      y_data_(data),
+      u_data_(y_data_ + y_pitch_ * decoded_height_),
+      v_data_(u_data_ + uv_pitch_ * decoded_height_ / 2) {}
 
 ShellVideoDataAllocator::YV12Param::YV12Param(int width,
                                               int height,
diff --git a/src/media/base/shell_video_data_allocator.h b/src/media/base/shell_video_data_allocator.h
index 1a61a06..ca164a2 100644
--- a/src/media/base/shell_video_data_allocator.h
+++ b/src/media/base/shell_video_data_allocator.h
@@ -47,7 +47,8 @@
    public:
     YV12Param(int decoded_width,
               int decoded_height,
-              const gfx::Rect& visible_rect);
+              const gfx::Rect& visible_rect,
+              uint8* data);
 
     // Create with data pointer to individual planes. All pointers should be in
     // the same memory block controlled by the accompanied FrameBuffer passed to
diff --git a/src/media/base/video_resolution.h b/src/media/base/video_resolution.h
new file mode 100644
index 0000000..714cca1
--- /dev/null
+++ b/src/media/base/video_resolution.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef MEDIA_BASE_VIDEO_RESOLUTION_H_
+#define MEDIA_BASE_VIDEO_RESOLUTION_H_
+
+#include "media/base/media_export.h"
+#include "ui/gfx/size.h"
+
+namespace media {
+
+// Enumerates the various representations of the resolution of videos.  Note
+// that except |kVideoResolutionInvalid|, all other values are guaranteed to be
+// in the same order as its (width, height) pair.
+enum VideoResolution {
+  kVideoResolution1080p,  // 1920 x 1080
+  kVideoResolution2k,     // 2560 x 1440
+  kVideoResolution4k,     // 3840 x 2160
+  kVideoResolutionInvalid
+};
+
+inline VideoResolution GetVideoResolution(int width, int height) {
+  if (width <= 1920 && height <= 1080) {
+    return kVideoResolution1080p;
+  }
+  if (width <= 2560 && height <= 1440) {
+    return kVideoResolution2k;
+  }
+  if (width <= 3840 && height <= 2160) {
+    return kVideoResolution4k;
+  }
+  return kVideoResolutionInvalid;
+}
+
+inline VideoResolution GetVideoResolution(const gfx::Size& size) {
+  return GetVideoResolution(size.width(), size.height());
+}
+
+}  // namespace media
+
+#endif  // MEDIA_BASE_VIDEO_RESOLUTION_H_
diff --git a/src/media/filters/shell_audio_decoder_impl.cc b/src/media/filters/shell_audio_decoder_impl.cc
index a38259a..2141df3 100644
--- a/src/media/filters/shell_audio_decoder_impl.cc
+++ b/src/media/filters/shell_audio_decoder_impl.cc
@@ -30,7 +30,7 @@
 using base::Time;
 using base::TimeDelta;
 
-const size_t kSamplesPerFrame = mp4::AAC::kSamplesPerFrame;
+const size_t kFramesPerAccessUnit = mp4::AAC::kFramesPerAccessUnit;
 
 namespace {
 
@@ -334,7 +334,7 @@
                    "ShellAudioDecoderImpl::DecodeBuffer() data decoded.",
                    "timestamp", buffer->GetTimestamp().InMicroseconds());
       DCHECK_EQ(buffer->GetDataSize(),
-                kSamplesPerFrame * bits_per_channel() / 8 * num_channels_);
+                kFramesPerAccessUnit * bits_per_channel() / 8 * num_channels_);
 
       PipelineStatistics statistics;
       statistics.audio_bytes_decoded = buffer->GetDataSize();
diff --git a/src/media/filters/shell_audio_renderer_impl.cc b/src/media/filters/shell_audio_renderer_impl.cc
index a6cc8ac..81b5115 100644
--- a/src/media/filters/shell_audio_renderer_impl.cc
+++ b/src/media/filters/shell_audio_renderer_impl.cc
@@ -247,10 +247,10 @@
   decrypting_demuxer_stream_ = decrypting_demuxer_stream;
 
   // construct audio parameters for the sink
-  audio_parameters_ =
-      AudioParameters(AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
-                      decoder_->samples_per_second(),
-                      decoder_->bits_per_channel(), mp4::AAC::kSamplesPerFrame);
+  audio_parameters_ = AudioParameters(
+      AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+      decoder_->samples_per_second(), decoder_->bits_per_channel(),
+      mp4::AAC::kFramesPerAccessUnit);
 
   state_ = kPaused;
 
@@ -486,16 +486,16 @@
         if (end_of_stream_state_ == kWaitingForEOS) {
           // Normal decode event
           rendered_timestamp_ = buffered_timestamp_;
-          frames_rendered = mp4::AAC::kSamplesPerFrame;
+          frames_rendered = mp4::AAC::kFramesPerAccessUnit;
         }
         if (end_of_stream_state_ == kReceivedEOS) {
           end_of_stream_state_ = kRenderedEOS;
         }
         if (end_of_stream_state_ == kRenderedEOS) {
           const int bytes_per_sample = audio_parameters_.bits_per_sample() / 8;
-          // TODO: Change this to DCHECK_LE and fill only kSamplesPerFrame
+          // TODO: Change this to DCHECK_LE and fill only kFramesPerAccessUnit
           // instead of dest->frames() once we support Read with arbitrary size.
-          DCHECK_EQ(mp4::AAC::kSamplesPerFrame * bytes_per_sample *
+          DCHECK_EQ(mp4::AAC::kFramesPerAccessUnit * bytes_per_sample *
                         audio_parameters_.channels(),
                     dest->frames() * dest->channels() * sizeof(float));
           // Write zeros (silence) to each channel
@@ -505,8 +505,8 @@
                 dest->frames() * sizeof(float);  // NOLINT(runtime/sizeof)
             memset(channel_data, 0, num_bytes);
           }
-          frames_rendered = mp4::AAC::kSamplesPerFrame;
-          uint64_t silence_ms = mp4::AAC::kSamplesPerFrame * 1000 /
+          frames_rendered = mp4::AAC::kFramesPerAccessUnit;
+          uint64_t silence_ms = mp4::AAC::kFramesPerAccessUnit * 1000 /
                                 audio_parameters_.sample_rate();
           silence_rendered_ += base::TimeDelta::FromMilliseconds(silence_ms);
         }
diff --git a/src/media/filters/shell_flv_parser.cc b/src/media/filters/shell_flv_parser.cc
index d5b3e23..5d517ad 100644
--- a/src/media/filters/shell_flv_parser.cc
+++ b/src/media/filters/shell_flv_parser.cc
@@ -111,6 +111,10 @@
     }
   }
 
+  if (duration_.InMilliseconds() == 0) {
+    return false;
+  }
+
   // We may have a valid duration by now and the reader may know the
   // length of the file in bytes, see if we can extrapolate a bitrate from
   // this.
@@ -250,13 +254,14 @@
 bool ShellFLVParser::ParseNextTag() {
   uint8 tag_buffer[kTagDownloadSize];
 
-  int bytes_read = 0;
-  if (!at_end_of_file_) {
-    // get previous tag size and header for next one
-    bytes_read =
-        reader_->BlockingRead(tag_offset_, kTagDownloadSize, tag_buffer);
+  if (at_end_of_file_) {
+    return false;
   }
 
+  // get previous tag size and header for next one
+  int bytes_read =
+      reader_->BlockingRead(tag_offset_, kTagDownloadSize, tag_buffer);
+
   // if that was the last tag in the stream detect the EOS and return. This
   // is where normal termination of an FLV stream will occur.
   if (bytes_read < kTagDownloadSize) {
diff --git a/src/media/filters/shell_mp4_map.cc b/src/media/filters/shell_mp4_map.cc
index a65e2c7..1d8b8d6 100644
--- a/src/media/filters/shell_mp4_map.cc
+++ b/src/media/filters/shell_mp4_map.cc
@@ -959,9 +959,8 @@
       }
     }
   }
-  DCHECK_GE(sample_number, stss_last_keyframe_);
-  DCHECK_LT(sample_number, stss_next_keyframe_);
-  return true;
+  return sample_number >= stss_last_keyframe_ &&
+         sample_number < stss_next_keyframe_;
 }
 
 // The stts table has the following per-entry layout:
diff --git a/src/media/filters/shell_mp4_parser.cc b/src/media/filters/shell_mp4_parser.cc
index b72f183..20ea082 100644
--- a/src/media/filters/shell_mp4_parser.cc
+++ b/src/media/filters/shell_mp4_parser.cc
@@ -139,7 +139,10 @@
   base::TimeDelta timestamp;
   base::TimeDelta duration;
   if (type == DemuxerStream::AUDIO) {
-    DCHECK_NE(audio_time_scale_hz_, 0);
+    if (audio_time_scale_hz_ == 0) {
+      DLOG(ERROR) << "|audio_time_scale_hz_| cannot be 0.";
+      return NULL;
+    }
     if (!audio_map_->GetSize(audio_sample_, size) ||
         !audio_map_->GetOffset(audio_sample_, offset) ||
         !audio_map_->GetDuration(audio_sample_, duration_ticks) ||
@@ -183,6 +186,10 @@
       first_audio_hole_ = timestamp + duration;
     }
   } else if (type == DemuxerStream::VIDEO) {
+    if (video_time_scale_hz_ == 0) {
+      DLOG(ERROR) << "|video_time_scale_hz_| cannot be 0.";
+      return NULL;
+    }
     if (!video_map_->GetSize(video_sample_, size) ||
         !video_map_->GetOffset(video_sample_, offset) ||
         !video_map_->GetDuration(video_sample_, duration_ticks) ||
@@ -197,7 +204,6 @@
       }
     }
     video_sample_++;
-    DCHECK_NE(video_time_scale_hz_, 0);
     timestamp = TicksToTime(timestamp_ticks, video_time_scale_hz_);
     duration = TicksToTime(duration_ticks, video_time_scale_hz_);
     // due to b-frames it's much more likely we'll encounter discontinuous
@@ -221,8 +227,14 @@
 }
 
 bool ShellMP4Parser::SeekTo(base::TimeDelta timestamp) {
-  DCHECK_NE(video_time_scale_hz_, 0);
-  DCHECK_NE(audio_time_scale_hz_, 0);
+  if (audio_time_scale_hz_ == 0 || video_time_scale_hz_ == 0) {
+    DLOG_IF(ERROR, audio_time_scale_hz_ == 0)
+        << "|audio_time_scale_hz_| cannot be 0.";
+    DLOG_IF(ERROR, video_time_scale_hz_ == 0)
+        << "|video_time_scale_hz_| cannot be 0.";
+    return false;
+  }
+
   // get video timestamp in video time units
   uint64 video_ticks = TimeToTicks(timestamp, video_time_scale_hz_);
   // find nearest keyframe from map, make it our next video sample
@@ -682,7 +694,7 @@
     return false;
   }
   uint32 time_scale_hz = endian_util::load_uint32_big_endian(mvhd + 12);
-  if (!time_scale_hz) {
+  if (time_scale_hz == 0) {
     DLOG(WARNING) << "got 0 time scale for mvhd";
     return false;
   }
@@ -698,12 +710,20 @@
 base::TimeDelta ShellMP4Parser::TicksToTime(uint64 ticks,
                                             uint32 time_scale_hz) {
   DCHECK_NE(time_scale_hz, 0);
+
+  if (time_scale_hz == 0) {
+    return base::TimeDelta::FromSeconds(0);
+  }
   return base::TimeDelta::FromMicroseconds((ticks * 1000000ULL) /
                                            time_scale_hz);
 }
 
 uint64 ShellMP4Parser::TimeToTicks(base::TimeDelta time, uint32 time_scale_hz) {
-  DCHECK(time_scale_hz);
+  DCHECK_NE(time_scale_hz, 0);
+
+  if (time_scale_hz == 0) {
+    return 0;
+  }
   return (time.InMicroseconds() * time_scale_hz) / 1000000ULL;
 }
 
diff --git a/src/media/filters/shell_raw_audio_decoder_linux.cc b/src/media/filters/shell_raw_audio_decoder_linux.cc
index 1316040..40785c5 100644
--- a/src/media/filters/shell_raw_audio_decoder_linux.cc
+++ b/src/media/filters/shell_raw_audio_decoder_linux.cc
@@ -311,7 +311,7 @@
 
     if (decoded_audio_size > 0) {
       // Copy the audio samples into an output buffer.
-      int buffer_size = kSampleSizeInBytes * mp4::AAC::kSamplesPerFrame *
+      int buffer_size = kSampleSizeInBytes * mp4::AAC::kFramesPerAccessUnit *
                         codec_context_->channels;
       output = decoder_buffer_pool_.Allocate(buffer_size);
       DCHECK(output);
@@ -319,7 +319,7 @@
       // requirement. This should eventually be lifted.
       ResampleToInterleavedFloat(
           codec_context_->sample_fmt, codec_context_->channel_layout,
-          samples_per_second_, mp4::AAC::kSamplesPerFrame,
+          samples_per_second_, mp4::AAC::kFramesPerAccessUnit,
           av_frame_->extended_data,
           reinterpret_cast<uint8*>(output->GetWritableData()));
       output->SetTimestamp(output_timestamp_helper_->GetTimestamp());
diff --git a/src/media/filters/shell_raw_audio_decoder_stub.cc b/src/media/filters/shell_raw_audio_decoder_stub.cc
index 1b903d4..6231cc2 100644
--- a/src/media/filters/shell_raw_audio_decoder_stub.cc
+++ b/src/media/filters/shell_raw_audio_decoder_stub.cc
@@ -77,7 +77,7 @@
   }
 
   decoded_buffer_size_ =
-      kSampleSizeInBytes * channel_count * mp4::AAC::kSamplesPerFrame;
+      kSampleSizeInBytes * channel_count * mp4::AAC::kFramesPerAccessUnit;
   return true;
 }
 
diff --git a/src/media/filters/shell_raw_video_decoder_linux.cc b/src/media/filters/shell_raw_video_decoder_linux.cc
index 5d873a4..703ac46 100644
--- a/src/media/filters/shell_raw_video_decoder_linux.cc
+++ b/src/media/filters/shell_raw_video_decoder_linux.cc
@@ -225,7 +225,8 @@
   // It is worth revisiting if we are going to release Linux as a production
   // platform.
   YV12Param param(av_frame_->width, av_frame_->height,
-                  gfx::Rect(av_frame_->width, av_frame_->height));
+                  gfx::Rect(av_frame_->width, av_frame_->height),
+                  frame_buffer->data());
   // We have to make a copy of the frame buffer as the frame buffer retrieved
   // from |av_frame_->opaque| may still be used by Ffmpeg.
   size_t yv12_frame_size =
diff --git a/src/media/filters/shell_raw_video_decoder_stub.cc b/src/media/filters/shell_raw_video_decoder_stub.cc
index 9226792..333cdec 100644
--- a/src/media/filters/shell_raw_video_decoder_stub.cc
+++ b/src/media/filters/shell_raw_video_decoder_stub.cc
@@ -53,7 +53,7 @@
   scoped_refptr<FrameBuffer> frame_buffer =
       allocator_->AllocateFrameBuffer(yuv_size, 1);
   YV12Param param(natural_size_.width(), natural_size_.height(),
-                  gfx::Rect(natural_size_));
+                  gfx::Rect(natural_size_), frame_buffer->data());
   scoped_refptr<VideoFrame> frame =
       allocator_->CreateYV12Frame(frame_buffer, param, buffer->GetTimestamp());
   decode_cb.Run(FRAME_DECODED, frame);
diff --git a/src/media/filters/shell_video_decoder_impl.cc b/src/media/filters/shell_video_decoder_impl.cc
index a9555fd..96e24b7 100644
--- a/src/media/filters/shell_video_decoder_impl.cc
+++ b/src/media/filters/shell_video_decoder_impl.cc
@@ -69,8 +69,8 @@
 
   VideoDecoderConfig decoder_config;
   decoder_config.CopyFrom(demuxer_stream_->video_decoder_config());
-  DLOG(INFO) << "Configuration at Start: "
-             << decoder_config.AsHumanReadableString();
+  LOG(INFO) << "Configuration at Start: "
+            << decoder_config.AsHumanReadableString();
 
   raw_decoder_ = raw_video_decoder_factory_->Create(
       decoder_config, demuxer_stream_->GetDecryptor(),
@@ -175,8 +175,8 @@
   if (demuxer_status == DemuxerStream::kConfigChanged) {
     VideoDecoderConfig decoder_config;
     decoder_config.CopyFrom(demuxer_stream_->video_decoder_config());
-    DLOG(INFO) << "Configuration Changed: "
-               << decoder_config.AsHumanReadableString();
+    LOG(INFO) << "Configuration Changed: "
+              << decoder_config.AsHumanReadableString();
     // One side effect of asking for the video configuration is that
     // the MediaSource demuxer stack uses that request to determine
     // that the video decoder has updated its configuration.
diff --git a/src/media/media.gyp b/src/media/media.gyp
index e020dc1..c2faa35 100644
--- a/src/media/media.gyp
+++ b/src/media/media.gyp
@@ -609,8 +609,11 @@
                 'filters/shell_raw_video_decoder_ps4.h',
                 'filters/shell_raw_vp9_decoder_ps4.cc',
                 'filters/shell_raw_vp9_decoder_ps4.h',
+                'filters/videodec2_working_memory_ps4.cc',
+                'filters/videodec2_working_memory_ps4.h',
               ],
               'dependencies' : [
+                '<(DEPTH)/nb/nb.gyp:nb',
                 '<(DEPTH)/third_party/libvpx_gpu/libvpx_gpu.gyp:libvpx_gpu',
               ],
             }],
diff --git a/src/media/mp4/aac.h b/src/media/mp4/aac.h
index 1dc1b70..1f581e5 100644
--- a/src/media/mp4/aac.h
+++ b/src/media/mp4/aac.h
@@ -23,6 +23,10 @@
 // for more details.
 class MEDIA_EXPORT AAC {
  public:
+  // Size in bytes of the ADTS header added by ConvertEsdsToADTS().
+  static const size_t kADTSHeaderSize = 7;
+  static const size_t kFramesPerAccessUnit = 1024;
+
   AAC();
   ~AAC();
 
@@ -50,10 +54,6 @@
   const std::vector<uint8>& raw_data() const { return raw_data_; }
 #endif  // COBALT_WIN
 
-  // Size in bytes of the ADTS header added by ConvertEsdsToADTS().
-  static const size_t kADTSHeaderSize = 7;
-  static const size_t kSamplesPerFrame = 1024;
-
  private:
   bool SkipDecoderGASpecificConfig(BitReader* bit_reader) const;
   bool SkipErrorSpecificConfig() const;
diff --git a/src/media/player/mime_util.cc b/src/media/player/mime_util.cc
index 2d1d9ee..86b0a5b 100644
--- a/src/media/player/mime_util.cc
+++ b/src/media/player/mime_util.cc
@@ -451,9 +451,14 @@
 #if defined(__LB_ANDROID__)  // Assume Android supports everything.
   { "video/webm", "vorbis,vp8,vp8.0,vp9" },
   { "audio/webm", "vorbis" },
-#elif defined(ENABLE_WEB_VP9)
-    {"video/webm", "vp9"},
-    {"audio/webm", ""},
+#elif defined(OS_STARBOARD)
+#if SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+  {"video/webm", "vp9"},
+  {"audio/webm", ""},
+#else  // SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
+  {"video/webm", ""},
+  {"audio/webm", ""},
+#endif  // SB_HAS(MEDIA_WEBM_VP9_SUPPORT)
 #elif defined(__LB_SHELL__) || defined(COBALT)
   // No other platforms support webm.
   { "video/webm", "" },
diff --git a/src/nb/fixed_no_free_allocator.cc b/src/nb/fixed_no_free_allocator.cc
index 062f17c..3722da6 100644
--- a/src/nb/fixed_no_free_allocator.cc
+++ b/src/nb/fixed_no_free_allocator.cc
@@ -34,6 +34,11 @@
   uint8_t* aligned_next_memory =
       AsPointer(AlignUp(AsInteger(next_memory_), alignment));
 
+  if (aligned_next_memory + size < aligned_next_memory) {
+    // "aligned_next_memory + size" overflows.
+    return NULL;
+  }
+
   if (aligned_next_memory + size > memory_end_) {
     // We don't have enough memory available to make this allocation.
     return NULL;
diff --git a/src/net/net.gyp b/src/net/net.gyp
index d6dab37..3d7b9d4 100644
--- a/src/net/net.gyp
+++ b/src/net/net.gyp
@@ -129,8 +129,6 @@
         'base/data_url.h',
         'base/default_server_bound_cert_store.cc',
         'base/default_server_bound_cert_store.h',
-        'base/directory_lister.cc',
-        'base/directory_lister.h',
         'base/dns_reloader.cc',
         'base/dns_reloader.h',
         'base/dns_util.cc',
@@ -985,6 +983,9 @@
             ['exclude', 'disk_cache/cache_util_posix.cc'],
             ['exclude', 'disk_cache/file_posix.cc'],
             ['exclude', 'disk_cache/mapped_file_posix.cc'],
+            # we don't use the directory lister
+            ['exclude', 'base/directory_lister.cc'],
+            ['exclude', 'base/directory_lister.h'],
             # or SDCH, Shared Dictionary Compression over HTTP
             ['exclude', 'sdch'],
             # exclude any v8-specific bindings
@@ -1528,7 +1529,6 @@
         'base/crl_set_unittest.cc',
         'base/data_url_unittest.cc',
         'base/default_server_bound_cert_store_unittest.cc',
-        'base/directory_lister_unittest.cc',
         'base/dns_util_unittest.cc',
         'base/dnsrr_resolver_unittest.cc',
         'base/escape_unittest.cc',
@@ -2076,6 +2076,7 @@
             ['exclude', 'python_utils_unittest'],
             ['exclude', 'proxy_script_fetcher_impl_unittest'],
             ['exclude', 'x509_cert_types_unittest'],  # ParseDistinguishedName() only exists for mac/win
+            ['exclude', 'directory_lister_unittest'],  # Not used.
             # FTP is not supported
             ['exclude', 'ftp_auth_cache_unittest'],
             ['exclude', 'ftp_ctrl_response_buffer_unittest'],
@@ -2389,7 +2390,7 @@
           'variables': {
             'executable_name': 'net_unittests',
           },
-          'includes': [ '../cobalt/build/deploy.gypi' ],
+          'includes': [ '../starboard/build/deploy.gypi' ],
         },
       ],
     }],
diff --git a/src/net/socket/transport_client_socket_unittest.cc b/src/net/socket/transport_client_socket_unittest.cc
index a7a6edf..317b713 100644
--- a/src/net/socket/transport_client_socket_unittest.cc
+++ b/src/net/socket/transport_client_socket_unittest.cc
@@ -105,6 +105,14 @@
   // Find a free port to listen on
   scoped_refptr<TCPListenSocket> sock;
   int port;
+#if defined(STARBOARD)
+  // Let the system choose a port for us.
+  sock = TCPListenSocket::CreateAndListen("127.0.0.1", 0, this);
+  ASSERT_TRUE(sock != NULL);
+  IPEndPoint address;
+  ASSERT_TRUE(sock->GetLocalAddress(&address) == 0);
+  port = address.port();
+#else
   // Range of ports to listen on.  Shouldn't need to try many.
   const int kMinPort = 10100;
   const int kMaxPort = 10200;
@@ -116,6 +124,7 @@
     if (sock.get())
       break;
   }
+#endif
   ASSERT_TRUE(sock != NULL);
   listen_sock_ = sock;
   listen_port_ = port;
diff --git a/src/sql/sql.gyp b/src/sql/sql.gyp
index 23fd2eb..8d354f9 100644
--- a/src/sql/sql.gyp
+++ b/src/sql/sql.gyp
@@ -110,7 +110,7 @@
           'variables': {
             'executable_name': 'sql_unittests',
           },
-          'includes': [ '../cobalt/build/deploy.gypi' ],
+          'includes': [ '../starboard/build/deploy.gypi' ],
         },
       ],
     }],
diff --git a/src/starboard/README.md b/src/starboard/README.md
index f5cf36f..3d35ee3 100644
--- a/src/starboard/README.md
+++ b/src/starboard/README.md
@@ -7,14 +7,8 @@
 
 ## Current State
 
-Starboard is still in development, and now runs Cobalt. The biggest things that
-are missing, but coming soon, are:
-
-  * Media support. Some APIs have been defined, but they are not complete, they
-    are not wired into Cobalt, they aren't yet implemented, and they are subject
-    to change.
-  * Blitter support. This is support for a hardware accelerated 2D blitter,
-    which some older platforms will have instead of OpenGL.
+Desktop Linux Cobalt is fully implemented on top of Starboard, and version 1 of
+the Starboard API is mostly locked down.
 
 
 ## Interesting Source Locations
@@ -141,9 +135,19 @@
 valid if you copy it to a new directory. You can then incrementally replace
 files with new implementations as necessary.
 
-For example, if your device runs Linux, you should start from linux.
+The cleanest, simplest starting point is from the Stub reference
+implementation. Nothing will work, but you should be able to compile and link it
+with your toolchain. You can then replace stub implementations with
+implementations from `src/starboard/shared` or your own custom implementations
+module-by-module, until you have gone through all modules.
 
-Rename the `x64x11/` directory to `<binary-variant>` (e.g. `mipseb`).
+You may also choose to copy either the Desktop Linux or Raspberry Pi ports and
+work backwards fixing things that don't compile or work on your platform.
+
+For example, for `bobbox-mipsel`, you might do:
+
+    mkdir -p src/third_party/starboard/bobbox
+    cp -R src/starboard/stub src/third_party/starboard/bobbox/mipsel
 
 Modify the files in `<binary-variant>/` as appropriate (you will probably be
 coming back to these files a lot).
@@ -154,9 +158,6 @@
 `src/` directory of your source tree. Otherwise, files are assumed to be
 relative to the directory the `.gyp` or `.gypi` file is in.
 
-
-### IV. Add Your Platform Configurations to cobalt_gyp
-
 In order to use a new platform configuration in a build, you need to ensure that
 you have a `gyp_configuration.py`, `gyp_configuration.gypi`, and
 `starboard_platform.gypi` in their own directory for each binary variant, plus
@@ -165,28 +166,30 @@
 files, and then calculate a port name based on the directories between
 `src/third_party/starboard` and your `gyp_configuration.*` files. (e.g. for
 `src/third_party/starboard/bobbox/mipseb/gyp_configuration.py`, it would choose
-the port name `bobbox_mipseb`.)
+the platform configuration name `bobbox-mipseb`.)
 
-  1. Set up `gyp_configuration.py`
-      1. Copy `src/starboard/linux/x64x11/gyp_configuration.py` to
-         `src/third_party/starboard/<family-name>/<binary-variant>/gyp_configuration.py`.
-         You may also consider copying from another reference platform, like `raspi-1`.
-      1. In `gyp_configuration.py`
-          1. In the `_PlatformConfig.__init__()` function, remove checks for Clang
-             or GOMA.
-          1. In the `CreatePlatformConfig()` function, pass your
-             `<platform-configuration>` as the parameter to the _PlatformConfig
-             constructor, like `return _PlatformConfig('bobbox-mipseb')`.
-        1. In `GetVariables`
-            1. Set `'clang': 1` if your toolchain is clang.
-            1. Delete other variables in that function that are not needed for
-               your platform.
-            1. In `GetEnvironmentVariables`, set the dictionary values to point
-               to the toolchain analogs for the toolchain for your platform.
-  1. Set up `gyp_configuration.gypi`
-      1. Copy `src/starboard/linux/x64x11/gyp_configuration.gypi` to
-         `src/third_party/starboard/<family-name>/<binary-variant>/gyp_configuration.gypi`.
-         You may also consider copying from another reference platform, like `raspi-1`.
+
+### IV. A New Port, Step-by-Step
+
+  1. Recursively copy `src/starboard/stub` to
+     `src/third_party/starboard/<family-name>/<binary-variant>`.  You may also
+     consider copying from another reference platform, like `raspi-1` or
+     `linux-x64x11`.
+  1. In `gyp_configuration.py`
+      1. In the `CreatePlatformConfig()` function, pass your
+         `<platform-configuration>` as the parameter to the PlatformConfig
+         constructor, like `return PlatformConfig('bobbox-mipseb')`.
+      1. In `GetVariables`
+          1. Set `'clang': 1` if your toolchain is clang.
+          1. Delete other variables in that function that are not needed for
+             your platform.
+      1. In `GetEnvironmentVariables`, set the dictionary values to point to the
+         toolchain analogs for the toolchain for your platform.
+  1. In `gyp_configuration.gypi`
+      1. Update the names of the configurations and the default_configuration to
+         be `<platform-configuation>_<build-type>` for your platform
+         configuration name, where `<build-type>` is one of `debug`, `devel`,
+         `qa`, `gold`.
       1. Update your platform variables.
           1. Set `'target_arch'` to your architecture: `'arm'`, `'ppc'`,
              `'x64'`, `'x86'`, `'mips'`
@@ -202,6 +205,12 @@
          different for someone else.
       1. Update the global defines in `'target_defaults'.'defines'`, if
          necessary.
+  1. Go through `configuration_public.h` and adjust all the configuration values
+     as appropriate for your platform.
+  1. Update `starboard_platform.gyp` to point at all the source files you want
+     to build as part of your new Starboard implementation (as mentioned above).
+  1. Update `atomic_public.h` and `thread_types_public.h` as necessary to point
+     at the appropriate shared or custom implementations.
 
 
 You should now be able to run gyp with your new port. From your `src/` directory:
diff --git a/src/starboard/__init__.py b/src/starboard/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/starboard/__init__.py
diff --git a/src/starboard/build/__init__.py b/src/starboard/build/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/starboard/build/__init__.py
diff --git a/src/starboard/build/convert_i18n_data.gypi b/src/starboard/build/convert_i18n_data.gypi
new file mode 100644
index 0000000..461e046
--- /dev/null
+++ b/src/starboard/build/convert_i18n_data.gypi
@@ -0,0 +1,57 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is meant to be included into an action to convert a set of XLB files
+# into files of a simpler format (e.g. CSV) in the product directory, e.g.
+# e.g. out/ps4_debug/content/data/i18n.
+#
+# To use this, create a gyp target with the following form:
+# {
+#   'target_name': 'convert_i18n_data',
+#   'type': 'none',
+#   'actions': [
+#     {
+#       'action_name': 'convert_i18n_data',
+#       'variables': {
+#         'input_files':
+#           '<!(find <(DEPTH)/cobalt/content/i18n/platform/linux/*.xlb)',
+#       },
+#       'includes': [ '../build/convert_i18n_data.gypi' ],
+#     },
+#   ],
+# },
+#
+# Meaning of the variables:
+#   input_files: list of paths to XLB files; directories are not expanded.
+
+{
+  'variables': {
+    'output_dir': '<(PRODUCT_DIR)/content/data/i18n'
+  },
+
+  'inputs': [
+    '<!@pymod_do_main(starboard.build.convert_i18n_data -o <@(output_dir) --inputs <@(input_files))',
+  ],
+
+  'outputs': [
+    '<!@pymod_do_main(starboard.build.convert_i18n_data -o <@(output_dir) --outputs <@(input_files))',
+  ],
+
+  'action': [
+    'python',
+    '<(DEPTH)/starboard/build/convert_i18n_data.py',
+    '-o', '<@(output_dir)',
+    '<@(input_files)',
+  ],
+}
diff --git a/src/starboard/build/convert_i18n_data.py b/src/starboard/build/convert_i18n_data.py
new file mode 100644
index 0000000..a34916a
--- /dev/null
+++ b/src/starboard/build/convert_i18n_data.py
@@ -0,0 +1,135 @@
+#!/usr/bin/python
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Converts XLB files into CSV files in a given output directory.
+
+Since the output of this script is intended to be use by GYP, all resulting
+paths are using Unix-style forward slashes.
+"""
+
+import argparse
+import os
+import posixpath
+import sys
+import xml.etree.ElementTree
+
+
+class WrongNumberOfArgumentsException(Exception):
+  pass
+
+
+def EscapePath(path):
+  """Returns a path with spaces escaped."""
+  return path.replace(' ', '\\ ')
+
+
+def ChangeSuffix(filename, new_suffix):
+  """Changes the suffix of |filename| to |new_suffix|. If no current suffix,
+  adds |new_suffix| to the end of |filename|."""
+  (root, ext) = os.path.splitext(filename)
+  return root + '.' + new_suffix
+
+
+def ConvertSingleFile(filename, output_filename):
+  """Converts a single input XLB file to a CSV file."""
+  tree = xml.etree.ElementTree.parse(filename)
+  root = tree.getroot()
+
+  # First child of the root is the list of messages.
+  messages = root[0]
+
+  # Write each message to the output file on its own line.
+  with open(output_filename, 'w') as output_file:
+    for msg in messages:
+      # Use ; as the separator. Which means it better not be in the name.
+      assert not (';' in msg.attrib['name'])
+      output_file.write(msg.attrib['name'])
+      output_file.write(';')
+      # Encode the text as UTF8 to accommodate special characters.
+      output_file.write(msg.text.encode('utf8'))
+      output_file.write('\n')
+
+
+def GetOutputs(files_to_convert, output_basedir):
+  """Returns a list of filenames relative to the output directory,
+  based on a list of input files."""
+  outputs = [];
+  for filename in files_to_convert:
+    dirname = posixpath.dirname(filename)
+    relative_filename = posixpath.relpath(filename, dirname)
+    relative_filename = ChangeSuffix(relative_filename, 'csv')
+    output_filename = posixpath.join(output_basedir, relative_filename)
+    outputs.append(output_filename)
+
+  return outputs
+
+
+def ConvertFiles(files_to_convert, output_basedir):
+  """Converts files and writes the result the given output directory."""
+  for filename in files_to_convert:
+    dirname = posixpath.dirname(filename)
+    relative_filename = posixpath.relpath(filename, dirname)
+    output_filename = posixpath.join(output_basedir, relative_filename)
+    output_dir = posixpath.dirname(output_filename)
+
+    if not os.path.exists(output_dir):
+      os.makedirs(output_dir)
+
+    output_filename = ChangeSuffix(output_filename, 'csv')
+    print 'Converting ' + filename + ' to ' + output_filename
+    ConvertSingleFile(filename, output_filename)
+
+
+def DoMain(argv):
+  """Called by GYP using pymod_do_main."""
+  parser = argparse.ArgumentParser()
+  parser.add_argument('-o', dest='output_dir', help='output directory')
+  parser.add_argument('--inputs', action='store_true', dest='list_inputs',
+                      help='prints a list of all input files')
+  parser.add_argument('--outputs', action='store_true', dest='list_outputs',
+                      help='prints a list of all output files')
+  parser.add_argument('input_paths', metavar='path', nargs='+',
+                      help='path to an input file or directory')
+  options = parser.parse_args(argv)
+
+  files_to_convert = [EscapePath(x) for x in options.input_paths]
+
+  if options.list_inputs:
+    return '\n'.join(files_to_convert)
+
+  if not options.output_dir:
+    raise WrongNumberOfArgumentsException('-o required.')
+
+  if options.list_outputs:
+    outputs = GetOutputs(files_to_convert, options.output_dir)
+    return '\n'.join(outputs)
+
+  ConvertFiles(files_to_convert, options.output_dir)
+  return
+
+
+def main(argv):
+  print 'Running... in main()'
+  try:
+    result = DoMain(argv[1:])
+  except WrongNumberOfArgumentsException, e:
+    print >> sys.stderr, e
+    return 1
+  if result:
+    print result
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(main(sys.argv))
diff --git a/src/starboard/build/copy_data.py b/src/starboard/build/copy_data.py
index c426dc0..cd1d6a2 100644
--- a/src/starboard/build/copy_data.py
+++ b/src/starboard/build/copy_data.py
@@ -14,6 +14,7 @@
 # limitations under the License.
 
 # This file is based on build/copy_test_data_ios.py
+
 """Copies data files or directories into a given output directory.
 
 Since the output of this script is intended to be use by GYP, all resulting
@@ -98,17 +99,11 @@
   """Called by GYP using pymod_do_main."""
   parser = argparse.ArgumentParser()
   parser.add_argument('-o', dest='output_dir', help='output directory')
-  parser.add_argument('--inputs',
-                      action='store_true',
-                      dest='list_inputs',
+  parser.add_argument('--inputs', action='store_true', dest='list_inputs',
                       help='prints a list of all input files')
-  parser.add_argument('--outputs',
-                      action='store_true',
-                      dest='list_outputs',
+  parser.add_argument('--outputs', action='store_true', dest='list_outputs',
                       help='prints a list of all output files')
-  parser.add_argument('input_paths',
-                      metavar='path',
-                      nargs='+',
+  parser.add_argument('input_paths', metavar='path', nargs='+',
                       help='path to an input file or directory')
   options = parser.parse_args(argv)
 
@@ -138,6 +133,5 @@
     print result
   return 0
 
-
 if __name__ == '__main__':
   sys.exit(main(sys.argv))
diff --git a/src/starboard/build/copy_test_data.gypi b/src/starboard/build/copy_test_data.gypi
index e4e47ed..13ac050 100644
--- a/src/starboard/build/copy_test_data.gypi
+++ b/src/starboard/build/copy_test_data.gypi
@@ -50,14 +50,14 @@
 
 {
   'inputs': [
-    '<!@pymod_do_main(copy_data --inputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data --inputs <(input_files))',
   ],
   'outputs': [
-    '<!@pymod_do_main(copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))',
+    '<!@pymod_do_main(starboard.build.copy_data -o <(PRODUCT_DIR)/content/dir_source_root/<(output_dir) --outputs <(input_files))',
   ],
   'action': [
     'python',
-    '<(DEPTH)/cobalt/build/copy_data.py',
+    '<(DEPTH)/starboard/build/copy_data.py',
     '-o', '<(PRODUCT_DIR)/content/dir_source_root/<(output_dir)',
     '<@(input_files)',
   ],
diff --git a/src/starboard/build/deploy.gypi b/src/starboard/build/deploy.gypi
new file mode 100644
index 0000000..ce7c9ce
--- /dev/null
+++ b/src/starboard/build/deploy.gypi
@@ -0,0 +1,54 @@
+# Copyright 2016 Google Inc. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is meant to be included into a target to provide a rule
+# to deploy a target on a target platform.
+#
+# The platform_deploy target should be defined in
+# starboard/<port_path>/platform_deploy.gyp. This target should perform
+# any per-executable logic that is specific to the platform. For example,
+# copying per-executable metadata files to the output directory.
+#
+# To use this, create a gyp target with the following form:
+# 'targets': [
+#   {
+#     'target_name': 'target_deploy',
+#     'type': 'none',
+#     'dependencies': [
+#       'target',
+#     ],
+#     'variables': {
+#       'executable_name': 'target',
+#     },
+#     'includes': [
+#       '../build/deploy.gypi',
+#     ],
+#   },
+#
+
+{
+  # Flag that will instruct gyp to create a special target in IDEs such as
+  # Visual Studio that can be used for launching a target.
+  'variables' : {
+    'ide_deploy_target': 1,
+  },
+
+  'conditions': [
+    ['OS=="starboard" and sb_has_deploy_step==1', {
+      'dependencies': [
+        '<(DEPTH)/<(starboard_path)/platform_deploy.gyp:platform_deploy',
+      ],
+    }],
+  ],
+}
diff --git a/src/starboard/configuration.h b/src/starboard/configuration.h
index 8dbf722..a106891 100644
--- a/src/starboard/configuration.h
+++ b/src/starboard/configuration.h
@@ -57,6 +57,9 @@
 // Determines at compile-time an inherent aspect of this platform.
 #define SB_IS(SB_FEATURE) (defined(SB_IS_##SB_FEATURE) && SB_IS_##SB_FEATURE)
 
+// Determines at compile-time whether this platform has a quirk.
+#define SB_HAS_QUIRK(SB_FEATURE) (defined(SB_HAS_QUIRK_##SB_FEATURE) && SB_HAS_QUIRK_##SB_FEATURE)
+
 // Determines at compile-time if this platform implements a given Starboard API
 // version number (or above).
 #define SB_VERSION(SB_API) (SB_API_VERSION >= SB_API)
@@ -384,6 +387,10 @@
 #error "Your platform must define SB_HAS_BILINEAR_FILTERING_SUPPORT."
 #endif
 
+#if !defined(SB_HAS_NV12_TEXTURE_SUPPORT)
+#error "Your platform must define SB_HAS_NV12_TEXTURE_SUPPORT."
+#endif
+
 // --- Derived Configuration -------------------------------------------------
 
 // Whether the current platform is little endian.
diff --git a/src/starboard/file.h b/src/starboard/file.h
index 4cbd3e1..d1ecc11 100644
--- a/src/starboard/file.h
+++ b/src/starboard/file.h
@@ -18,6 +18,7 @@
 #define STARBOARD_FILE_H_
 
 #include "starboard/export.h"
+#include "starboard/log.h"
 #include "starboard/time.h"
 #include "starboard/types.h"
 
@@ -181,4 +182,60 @@
 }  // extern "C"
 #endif
 
+#ifdef __cplusplus
+namespace starboard {
+
+// A class that opens an SbFile in its constructor and closes it in its
+// destructor, so the file is open for the lifetime of the object. Member
+// functions call the corresponding SbFile function.
+class ScopedFile {
+ public:
+  ScopedFile(const char* path,
+             int flags,
+             bool* out_created,
+             SbFileError* out_error)
+      : file_(kSbFileInvalid) {
+    file_ = SbFileOpen(path, flags, out_created, out_error);
+  }
+
+  ScopedFile(const char* path, int flags, bool* out_created)
+      : file_(kSbFileInvalid) {
+    file_ = SbFileOpen(path, flags, out_created, NULL);
+  }
+
+  ScopedFile(const char* path, int flags) : file_(kSbFileInvalid) {
+    file_ = SbFileOpen(path, flags, NULL, NULL);
+  }
+
+  ~ScopedFile() { SbFileClose(file_); }
+
+  SbFile file() const { return file_; }
+
+  bool IsValid() const { return SbFileIsValid(file_); }
+
+  int64_t Seek(SbFileWhence whence, int64_t offset) const {
+    return SbFileSeek(file_, whence, offset);
+  }
+
+  int Read(char* data, int size) const { return SbFileRead(file_, data, size); }
+
+  int Write(const char* data, int size) const {
+    return SbFileWrite(file_, data, size);
+  }
+
+  bool Truncate(int64_t length) const { return SbFileTruncate(file_, length); }
+
+  bool Flush() const { return SbFileFlush(file_); }
+
+  bool GetInfo(SbFileInfo* out_info) const {
+    return SbFileGetInfo(file_, out_info);
+  }
+
+ private:
+  SbFile file_;
+};
+
+}  // namespace starboard
+#endif  // ifdef __cplusplus
+
 #endif  // STARBOARD_FILE_H_
diff --git a/src/starboard/linux/shared/gyp_configuration.py b/src/starboard/linux/shared/gyp_configuration.py
index a674378..cb6edb4 100644
--- a/src/starboard/linux/shared/gyp_configuration.py
+++ b/src/starboard/linux/shared/gyp_configuration.py
@@ -15,6 +15,7 @@
 
 import os
 
+from config.base import Configs
 import config.starboard
 import gyp_utils
 
@@ -22,7 +23,7 @@
 class PlatformConfig(config.starboard.PlatformConfigStarboard):
   """Starboard Linux platform configuration."""
 
-  def __init__(self, platform):
+  def __init__(self, platform, asan_enabled_by_default=True):
     super(PlatformConfig, self).__init__(platform)
 
     gyp_utils.CheckClangVersion()
@@ -32,6 +33,8 @@
     # correctly in the PATH.
     gyp_utils.FindAndInitGoma()
 
+    self.asan_default = 1 if asan_enabled_by_default else 0
+
   def GetBuildFormat(self):
     """Returns the desired build format."""
     # The comma means that ninja and qtcreator_ninja will be chained and use the
@@ -41,21 +44,17 @@
 
   def GetVariables(self, configuration):
     variables = super(PlatformConfig, self).GetVariables(configuration)
+    use_tsan = int(os.environ.get('USE_TSAN', 0))
+    # Enable ASAN by default for debug and devel builds only if USE_TSAN was not
+    # set to 1 in the environment.
+    use_asan_default = self.asan_default if not use_tsan and configuration in (
+        Configs.DEBUG, Configs.DEVEL) else 0
     variables.update({
         'clang': 1,
-        'use_asan': int(os.environ.get('USE_ASAN', 0)),
-        'use_tsan': int(os.environ.get('USE_TSAN', 0)),
+        'use_asan': int(os.environ.get('USE_ASAN', use_asan_default)),
+        'use_tsan': use_tsan,
     })
 
-    if int(os.environ.get('USE_FUZZING', 0)):
-      # Build configuration for fuzz testing.
-      variables['use_asan'] = 1
-      variables['use_tsan'] = 0
-      # Disable code that tries to bind ports. The machines that run fuzz
-      # testing may not permit that, and we don't handle it gracefully.
-      variables['in_app_dial'] = 0
-      variables['enable_remote_debugging'] = 0
-
     if variables.get('use_asan') == 1 and variables.get('use_tsan') == 1:
       raise RuntimeError('ASAN and TSAN are mutually exclusive')
     return variables
diff --git a/src/starboard/linux/x64directfb/configuration_public.h b/src/starboard/linux/x64directfb/configuration_public.h
index 032fa17..c891232 100644
--- a/src/starboard/linux/x64directfb/configuration_public.h
+++ b/src/starboard/linux/x64directfb/configuration_public.h
@@ -26,6 +26,11 @@
 // API afterwards since we'll have DirectFB available.
 #include "starboard/linux/x64x11/configuration_public.h"
 
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#undef SB_HAS_NV12_TEXTURE_SUPPORT
+#define SB_HAS_NV12_TEXTURE_SUPPORT 0
+
 // This configuration supports the blitter API (implemented via DirectFB).
 #undef SB_HAS_BLITTER
 #define SB_HAS_BLITTER 1
diff --git a/src/starboard/linux/x64directfb/gyp_configuration.py b/src/starboard/linux/x64directfb/gyp_configuration.py
index 34da360..0506121 100644
--- a/src/starboard/linux/x64directfb/gyp_configuration.py
+++ b/src/starboard/linux/x64directfb/gyp_configuration.py
@@ -18,14 +18,15 @@
 import sys
 
 # Import the shared Linux platform configuration.
-sys.path.append(os.path.realpath(os.path.join(os.path.dirname(__file__),
-                                              os.pardir, 'shared')))
+sys.path.append(os.path.realpath(os.path.join(
+    os.path.dirname(__file__), os.pardir, 'shared')))
 import gyp_configuration
 
 
 def CreatePlatformConfig():
   try:
-    return gyp_configuration.PlatformConfig('linux-x64directfb')
+    return gyp_configuration.PlatformConfig('linux-x64directfb',
+                                            asan_enabled_by_default=False)
   except RuntimeError as e:
     logging.critical(e)
     return None
diff --git a/src/starboard/linux/x64directfb/starboard_platform.gyp b/src/starboard/linux/x64directfb/starboard_platform.gyp
index e9ed5d5..279c8d9 100644
--- a/src/starboard/linux/x64directfb/starboard_platform.gyp
+++ b/src/starboard/linux/x64directfb/starboard_platform.gyp
@@ -300,6 +300,8 @@
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_session.cc',
         '<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
       ],
       'include_dirs': [
         '/usr/include/directfb',
diff --git a/src/starboard/linux/x64x11/configuration_public.h b/src/starboard/linux/x64x11/configuration_public.h
index 3bd1efb..f11107c 100644
--- a/src/starboard/linux/x64x11/configuration_public.h
+++ b/src/starboard/linux/x64x11/configuration_public.h
@@ -97,6 +97,12 @@
 // on the specifically pinned core.
 #define SB_HAS_CROSS_CORE_SCHEDULER 1
 
+// --- Graphics Configuration ------------------------------------------------
+
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
 // Include the Linux configuration that's common between all Desktop Linuxes.
 #include "starboard/linux/shared/configuration_public.h"
 
diff --git a/src/starboard/linux/x64x11/starboard_platform.gyp b/src/starboard/linux/x64x11/starboard_platform.gyp
index 867bc47..46ea9aa 100644
--- a/src/starboard/linux/x64x11/starboard_platform.gyp
+++ b/src/starboard/linux/x64x11/starboard_platform.gyp
@@ -261,6 +261,8 @@
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_session.cc',
         '<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
         '<(DEPTH)/starboard/shared/x11/application_x11.cc',
         '<(DEPTH)/starboard/shared/x11/window_create.cc',
         '<(DEPTH)/starboard/shared/x11/window_destroy.cc',
diff --git a/src/starboard/nplb/nplb.gyp b/src/starboard/nplb/nplb.gyp
index da5bd7b..0835148 100644
--- a/src/starboard/nplb/nplb.gyp
+++ b/src/starboard/nplb/nplb.gyp
@@ -234,6 +234,7 @@
       'variables': {
         'executable_name': 'nplb',
       },
+      'includes': [ '../build/deploy.gypi' ],
     },
   ],
 }
diff --git a/src/starboard/nplb/socket_accept_test.cc b/src/starboard/nplb/socket_accept_test.cc
index b22a389..f9e9b9e 100644
--- a/src/starboard/nplb/socket_accept_test.cc
+++ b/src/starboard/nplb/socket_accept_test.cc
@@ -24,11 +24,10 @@
 namespace nplb {
 namespace {
 
-const int kPort = 2048;
-
 TEST(SbSocketAcceptTest, RainyDayNoConnection) {
   // Set up a socket to listen.
-  SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort);
+  SbSocket server_socket =
+      CreateListeningTcpIpv4Socket(GetPortNumberForTests());
   if (!SbSocketIsValid(server_socket)) {
     return;
   }
@@ -60,7 +59,7 @@
 
 TEST(SbSocketAcceptTest, RainyDayNotListening) {
   // Set up a socket, but don't Bind or Listen.
-  SbSocket server_socket = CreateBoundTcpIpv4Socket(kPort);
+  SbSocket server_socket = CreateBoundTcpIpv4Socket(GetPortNumberForTests());
   if (!SbSocketIsValid(server_socket)) {
     return;
   }
diff --git a/src/starboard/nplb/socket_bind_test.cc b/src/starboard/nplb/socket_bind_test.cc
index b74126d..81cb4e8 100644
--- a/src/starboard/nplb/socket_bind_test.cc
+++ b/src/starboard/nplb/socket_bind_test.cc
@@ -28,7 +28,7 @@
 const void* kNull = NULL;
 
 TEST(SbSocketBindTest, RainyDayNullSocket) {
-  SbSocketAddress address = GetIpv4Unspecified(2048);
+  SbSocketAddress address = GetIpv4Unspecified(GetPortNumberForTests());
   EXPECT_EQ(kSbSocketErrorFailed, SbSocketBind(kSbSocketInvalid, &address));
 }
 
@@ -41,7 +41,7 @@
 
   // Even though that failed, binding the same socket now with 0.0.0.0:2048
   // should work.
-  SbSocketAddress address = GetIpv4Unspecified(2048);
+  SbSocketAddress address = GetIpv4Unspecified(GetPortNumberForTests());
   EXPECT_EQ(kSbSocketOk, SbSocketBind(server_socket, &address));
 
   EXPECT_TRUE(SbSocketDestroy(server_socket));
@@ -57,12 +57,12 @@
   EXPECT_TRUE(SbSocketIsValid(server_socket));
 
   // Binding with the wrong address type should fail.
-  SbSocketAddress address = GetIpv6Unspecified(2048);
+  SbSocketAddress address = GetIpv6Unspecified(GetPortNumberForTests());
   EXPECT_EQ(kSbSocketErrorFailed, SbSocketBind(server_socket, &address));
 
   // Even though that failed, binding the same socket now with 0.0.0.0:2048
   // should work.
-  address = GetIpv4Unspecified(2048);
+  address = GetIpv4Unspecified(GetPortNumberForTests());
   EXPECT_EQ(kSbSocketOk, SbSocketBind(server_socket, &address));
 
   EXPECT_TRUE(SbSocketDestroy(server_socket));
diff --git a/src/starboard/nplb/socket_get_local_address_test.cc b/src/starboard/nplb/socket_get_local_address_test.cc
index 5f29747..112f9a4 100644
--- a/src/starboard/nplb/socket_get_local_address_test.cc
+++ b/src/starboard/nplb/socket_get_local_address_test.cc
@@ -82,8 +82,7 @@
 }
 
 TEST(SbSocketGetLocalAddressTest, SunnyDayConnected) {
-  const int kPort = 2048;
-
+  const int kPort = GetPortNumberForTests();
   ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     return;
diff --git a/src/starboard/nplb/socket_helpers.cc b/src/starboard/nplb/socket_helpers.cc
index 922195b..6f9b35a 100644
--- a/src/starboard/nplb/socket_helpers.cc
+++ b/src/starboard/nplb/socket_helpers.cc
@@ -14,6 +14,7 @@
 
 #include "starboard/nplb/socket_helpers.h"
 
+#include "starboard/once.h"
 #include "starboard/socket.h"
 #include "starboard/socket_waiter.h"
 #include "starboard/thread.h"
@@ -22,6 +23,36 @@
 
 namespace starboard {
 namespace nplb {
+namespace {
+
+int port_number_for_tests = 0;
+SbOnceControl valid_port_once_control = SB_ONCE_INITIALIZER;
+
+void InitializePortNumberForTests() {
+  // Create a listening socket. Let the system choose a port for us.
+  SbSocket socket = CreateListeningTcpIpv4Socket(0);
+  SB_DCHECK(socket != kSbSocketInvalid);
+
+  // Query which port this socket was bound to and save it to valid_port_number.
+  SbSocketAddress socket_address = {0};
+  bool result = SbSocketGetLocalAddress(socket, &socket_address);
+  SB_DCHECK(result);
+  port_number_for_tests = socket_address.port;
+
+  // Clean up the socket.
+  result = SbSocketDestroy(socket);
+  SB_DCHECK(result);
+}
+}  // namespace
+
+int GetPortNumberForTests() {
+#if defined(SB_SOCKET_OVERRIDE_PORT_FOR_TESTS)
+  return SB_SOCKET_OVERRIDE_PORT_FOR_TESTS;
+#else
+  SbOnce(&valid_port_once_control, &InitializePortNumberForTests);
+  return port_number_for_tests;
+#endif
+}
 
 bool IsUnspecified(const SbSocketAddress* address) {
   // Look at each piece of memory and make sure too many of them aren't zero.
diff --git a/src/starboard/nplb/socket_helpers.h b/src/starboard/nplb/socket_helpers.h
index 5a59489..5b4e5d7 100644
--- a/src/starboard/nplb/socket_helpers.h
+++ b/src/starboard/nplb/socket_helpers.h
@@ -43,6 +43,10 @@
 // address types.
 bool IsLocalhost(const SbSocketAddress* address);
 
+// Returns a valid port number that can be bound to for use in nplb tests.
+// This will always return the same port number.
+int GetPortNumberForTests();
+
 // Returns an IPv4 localhost address with the given port.
 SbSocketAddress GetIpv4Localhost(int port);
 
diff --git a/src/starboard/nplb/socket_is_connected_and_idle_test.cc b/src/starboard/nplb/socket_is_connected_and_idle_test.cc
index 020701a..ffe83f5 100644
--- a/src/starboard/nplb/socket_is_connected_and_idle_test.cc
+++ b/src/starboard/nplb/socket_is_connected_and_idle_test.cc
@@ -22,14 +22,13 @@
 namespace nplb {
 namespace {
 
-const int kPort = 2048;
-
 TEST(SbSocketIsConnectedAndIdleTest, RainyDayInvalidSocket) {
   EXPECT_FALSE(SbSocketIsConnectedAndIdle(kSbSocketInvalid));
 }
 
 TEST(SbSocketIsConnectedAndIdleTest, SunnyDay) {
-  ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     return;
   }
@@ -68,7 +67,8 @@
 }
 
 TEST(SbSocketIsConnectedAndIdleTest, SunnyDayListeningNotConnected) {
-  SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort);
+  SbSocket server_socket =
+      CreateListeningTcpIpv4Socket(GetPortNumberForTests());
   if (!SbSocketIsValid(server_socket)) {
     return;
   }
diff --git a/src/starboard/nplb/socket_is_connected_test.cc b/src/starboard/nplb/socket_is_connected_test.cc
index 2c65d0d..e69fc4d 100644
--- a/src/starboard/nplb/socket_is_connected_test.cc
+++ b/src/starboard/nplb/socket_is_connected_test.cc
@@ -21,14 +21,13 @@
 namespace nplb {
 namespace {
 
-const int kPort = 2048;
-
 TEST(SbSocketIsConnectedTest, RainyDayInvalidSocket) {
   EXPECT_FALSE(SbSocketIsConnected(kSbSocketInvalid));
 }
 
 TEST(SbSocketIsConnectedTest, SunnyDay) {
-  ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     return;
   }
@@ -61,7 +60,8 @@
 }
 
 TEST(SbSocketIsConnectedTest, SunnyDayListeningNotConnected) {
-  SbSocket server_socket = CreateListeningTcpIpv4Socket(kPort);
+  SbSocket server_socket =
+      CreateListeningTcpIpv4Socket(GetPortNumberForTests());
   if (!SbSocketIsValid(server_socket)) {
     return;
   }
diff --git a/src/starboard/nplb/socket_receive_from_test.cc b/src/starboard/nplb/socket_receive_from_test.cc
index 34f9215..5cd8c43 100644
--- a/src/starboard/nplb/socket_receive_from_test.cc
+++ b/src/starboard/nplb/socket_receive_from_test.cc
@@ -60,11 +60,11 @@
 }
 
 TEST(SbSocketReceiveFromTest, SunnyDay) {
-  const int kPort = 2048;
   const int kBufSize = 256 * 1024;
   const int kSockBufSize = kBufSize / 8;
 
-  ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     return;
   }
diff --git a/src/starboard/nplb/socket_waiter_wait_test.cc b/src/starboard/nplb/socket_waiter_wait_test.cc
index fd1962e..8b67583 100644
--- a/src/starboard/nplb/socket_waiter_wait_test.cc
+++ b/src/starboard/nplb/socket_waiter_wait_test.cc
@@ -56,13 +56,13 @@
 }
 
 TEST(SbSocketWaiterWaitTest, SunnyDay) {
-  const int kPort = 2048;
   const int kBufSize = 1024;
 
   SbSocketWaiter waiter = SbSocketWaiterCreate();
   EXPECT_TRUE(SbSocketWaiterIsValid(waiter));
 
-  ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     ADD_FAILURE();
     return;
@@ -148,7 +148,6 @@
 
 const char kAData[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
 const char kBData[] = "bb";
-const int kPort = 2048;
 
 void* AlreadyReadyEntryPoint(void* param) {
   AlreadyReadyContext* context = reinterpret_cast<AlreadyReadyContext*>(param);
@@ -204,7 +203,7 @@
   context.waiter = SbSocketWaiterCreate();
   ASSERT_TRUE(SbSocketWaiterIsValid(context.waiter));
 
-  context.trio = CreateAndConnect(kPort, kSocketTimeout);
+  context.trio = CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   ASSERT_TRUE(SbSocketIsValid(context.trio.server_socket));
 
   EXPECT_TRUE(SbSocketWaiterAdd(context.waiter, context.trio.client_socket,
diff --git a/src/starboard/nplb/socket_waiter_wait_timed_test.cc b/src/starboard/nplb/socket_waiter_wait_timed_test.cc
index 57946ad..0166743 100644
--- a/src/starboard/nplb/socket_waiter_wait_timed_test.cc
+++ b/src/starboard/nplb/socket_waiter_wait_timed_test.cc
@@ -47,13 +47,13 @@
 }
 
 TEST(SbSocketWaiterWaitTimedTest, SunnyDay) {
-  const int kPort = 2048;
   const int kBufSize = 1024;
 
   SbSocketWaiter waiter = SbSocketWaiterCreate();
   EXPECT_TRUE(SbSocketWaiterIsValid(waiter));
 
-  ConnectedTrio trio = CreateAndConnect(kPort, kSocketTimeout);
+  ConnectedTrio trio =
+      CreateAndConnect(GetPortNumberForTests(), kSocketTimeout);
   if (!SbSocketIsValid(trio.server_socket)) {
     ADD_FAILURE();
     return;
diff --git a/src/starboard/nplb/system_get_property_test.cc b/src/starboard/nplb/system_get_property_test.cc
index 4ad7b86..82f35d5 100644
--- a/src/starboard/nplb/system_get_property_test.cc
+++ b/src/starboard/nplb/system_get_property_test.cc
@@ -51,8 +51,8 @@
   BasicTest(kSbSystemPropertyChipsetModelNumber, false, true, __LINE__);
   BasicTest(kSbSystemPropertyFirmwareVersion, false, true, __LINE__);
   BasicTest(kSbSystemPropertyFriendlyName, true, true, __LINE__);
-  BasicTest(kSbSystemPropertyManufacturerName, true, true, __LINE__);
-  BasicTest(kSbSystemPropertyModelName, true, true, __LINE__);
+  BasicTest(kSbSystemPropertyManufacturerName, false, true, __LINE__);
+  BasicTest(kSbSystemPropertyModelName, false, true, __LINE__);
   BasicTest(kSbSystemPropertyNetworkOperatorName, false, true, __LINE__);
   BasicTest(kSbSystemPropertyPlatformName, true, true, __LINE__);
   BasicTest(kSbSystemPropertyPlatformUuid, true, true, __LINE__);
diff --git a/src/starboard/raspi/1/starboard_platform.gyp b/src/starboard/raspi/1/starboard_platform.gyp
index e1d104b..1b80d83 100644
--- a/src/starboard/raspi/1/starboard_platform.gyp
+++ b/src/starboard/raspi/1/starboard_platform.gyp
@@ -30,8 +30,8 @@
         '<(DEPTH)/starboard/linux/shared/system_get_connection_type.cc',
         '<(DEPTH)/starboard/linux/shared/system_get_device_type.cc',
         '<(DEPTH)/starboard/linux/shared/system_get_path.cc',
-        '<(DEPTH)/starboard/linux/shared/system_get_property.cc',
         '<(DEPTH)/starboard/linux/shared/system_has_capability.cc',
+        '<(DEPTH)/starboard/raspi/1/system_get_property.cc',
         '<(DEPTH)/starboard/raspi/shared/application_dispmanx.cc',
         '<(DEPTH)/starboard/raspi/shared/main.cc',
         '<(DEPTH)/starboard/raspi/shared/window_create.cc',
@@ -268,6 +268,8 @@
         '<(DEPTH)/starboard/shared/stub/drm_system_internal.h',
         '<(DEPTH)/starboard/shared/stub/drm_update_session.cc',
         '<(DEPTH)/starboard/shared/stub/media_is_supported.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
       ],
       'defines': [
         # This must be defined when building Starboard, and must not when
diff --git a/src/starboard/raspi/1/system_get_property.cc b/src/starboard/raspi/1/system_get_property.cc
new file mode 100644
index 0000000..9a849da
--- /dev/null
+++ b/src/starboard/raspi/1/system_get_property.cc
@@ -0,0 +1,68 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/log.h"
+#include "starboard/string.h"
+
+namespace {
+
+const char* kFriendlyName = "My Linux";
+const char* kPlatformName = "Linux armv7l";
+
+bool CopyStringAndTestIfSuccess(char* out_value,
+                                int value_length,
+                                const char* from_value) {
+  if (SbStringGetLength(from_value) + 1 > value_length)
+    return false;
+  SbStringCopy(out_value, from_value, value_length);
+  return true;
+}
+
+}  // namespace
+
+bool SbSystemGetProperty(SbSystemPropertyId property_id,
+                         char* out_value,
+                         int value_length) {
+  if (!out_value || !value_length) {
+    return false;
+  }
+
+  switch (property_id) {
+    case kSbSystemPropertyChipsetModelNumber:
+    case kSbSystemPropertyFirmwareVersion:
+    case kSbSystemPropertyManufacturerName:
+    case kSbSystemPropertyModelName:
+    case kSbSystemPropertyNetworkOperatorName:
+      return false;
+
+    case kSbSystemPropertyFriendlyName:
+      return CopyStringAndTestIfSuccess(out_value, value_length, kFriendlyName);
+
+    case kSbSystemPropertyPlatformName:
+      return CopyStringAndTestIfSuccess(out_value, value_length, kPlatformName);
+
+    case kSbSystemPropertyPlatformUuid:
+      SB_NOTIMPLEMENTED();
+      return CopyStringAndTestIfSuccess(out_value, value_length, "N/A");
+
+    default:
+      SB_DLOG(WARNING) << __FUNCTION__
+                       << ": Unrecognized property: " << property_id;
+      break;
+  }
+
+  return false;
+}
diff --git a/src/starboard/raspi/shared/configuration_public.h b/src/starboard/raspi/shared/configuration_public.h
index b625805..de26224 100644
--- a/src/starboard/raspi/shared/configuration_public.h
+++ b/src/starboard/raspi/shared/configuration_public.h
@@ -223,6 +223,10 @@
 // working properly.
 #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
 
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 1
+
 // --- Media Configuration ---------------------------------------------------
 
 // Specifies whether this platform has support for direct access to a decoder
diff --git a/src/starboard/shared/starboard/localized_strings.cc b/src/starboard/shared/starboard/localized_strings.cc
new file mode 100644
index 0000000..2639c53
--- /dev/null
+++ b/src/starboard/shared/starboard/localized_strings.cc
@@ -0,0 +1,153 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/shared/starboard/localized_strings.h"
+
+#include "starboard/file.h"
+#include "starboard/log.h"
+#include "starboard/system.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+
+namespace {
+
+std::string GetFilenameForLanguage(const std::string& language) {
+  const int kBufferSize = 256;
+  char buffer[kBufferSize];
+  bool got_path =
+      SbSystemGetPath(kSbSystemPathContentDirectory, buffer, kBufferSize);
+  if (!got_path) {
+    SB_DLOG(ERROR) << "Cannot get content path for i18n files.";
+    return std::string();
+  }
+
+  return std::string(buffer).append("/i18n/").append(language).append(".csv");
+}
+
+bool ReadFile(const std::string& filename, std::string* out_result) {
+  SB_DCHECK(filename.length() > 0);
+  SB_DCHECK(out_result);
+
+  ScopedFile file(filename.c_str(), kSbFileOpenOnly | kSbFileRead);
+  if (!file.IsValid()) {
+    SB_DLOG(WARNING) << "Cannot open i18n file: " << filename;
+    return false;
+  }
+
+  SbFileInfo file_info = {0};
+  bool got_info = file.GetInfo(&file_info);
+  if (!got_info) {
+    SB_DLOG(ERROR) << "Cannot get information for i18n file.";
+    return false;
+  }
+  SB_DCHECK(file_info.size > 0);
+
+  const int kMaxBufferSize = 16 * 1024;
+  if (file_info.size > kMaxBufferSize) {
+    SB_DLOG(ERROR) << "i18n file exceeds maximum size: " << file_info.size
+                   << " (" << kMaxBufferSize << ")";
+    return false;
+  }
+
+  char* buffer = new char[file_info.size];
+  SB_DCHECK(buffer);
+  int bytes_to_read = file_info.size;
+  char* buffer_pos = buffer;
+  while (bytes_to_read > 0) {
+    int bytes_read = file.Read(buffer_pos, bytes_to_read);
+    if (bytes_read < 0) {
+      SB_DLOG(ERROR) << "Read from i18n file failed.";
+      delete[] buffer;
+      return false;
+    }
+    bytes_to_read -= bytes_read;
+    buffer_pos += bytes_read;
+  }
+
+  *out_result = std::string(buffer, file_info.size);
+  delete[] buffer;
+  return true;
+}
+
+}  // namespace
+
+LocalizedStrings::LocalizedStrings(const std::string& language) {
+  bool did_load_strings = LoadStrings(language);
+
+  if (!did_load_strings) {
+    // Failed to load strings - try generic version of the language.
+    size_t dash = language.find_first_of("-_");
+    if (dash != std::string::npos) {
+      std::string generic_lang(language.c_str(), dash);
+      did_load_strings = LoadStrings(generic_lang);
+    }
+  }
+
+  SB_DCHECK(did_load_strings);
+}
+
+std::string LocalizedStrings::GetString(const std::string& id,
+                                        const std::string& fallback) const {
+  StringMap::const_iterator iter = strings_.find(id);
+  if (iter == strings_.end()) {
+    return fallback;
+  }
+  return iter->second;
+}
+
+bool LocalizedStrings::LoadStrings(const std::string& language) {
+  const std::string filename = GetFilenameForLanguage(language);
+  std::string file_contents;
+  if (!ReadFile(filename, &file_contents)) {
+    SB_DLOG(ERROR) << "Error reading i18n file.";
+    return false;
+  }
+  SB_DCHECK(file_contents.length() > 0);
+  SB_DCHECK(file_contents.back() == '\n');
+
+  // Each line of the file corresponds to one message (key/value).
+  size_t pos = 0;
+  while (true) {
+    size_t next_pos = file_contents.find("\n", pos);
+    if (next_pos == std::string::npos) {
+      break;
+    }
+    bool got_string =
+        LoadSingleString(std::string(file_contents, pos, next_pos - pos));
+    SB_DCHECK(got_string);
+    pos = next_pos + 1;
+  }
+
+  return true;
+}
+
+bool LocalizedStrings::LoadSingleString(const std::string& message) {
+  // A single message is a key/value pair with separator.
+  size_t separator_pos = message.find(';');
+  if (separator_pos == std::string::npos) {
+    SB_DLOG(ERROR) << "No separator found in: " << message;
+    return false;
+  }
+
+  const std::string key(message, 0, separator_pos);
+  const std::string value(message, separator_pos + 1);
+  strings_[key] = value;
+  return true;
+}
+
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
diff --git a/src/starboard/shared/starboard/localized_strings.h b/src/starboard/shared/starboard/localized_strings.h
new file mode 100644
index 0000000..fee9487
--- /dev/null
+++ b/src/starboard/shared/starboard/localized_strings.h
@@ -0,0 +1,61 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// A simple localized string table implementation.
+
+#ifndef STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_
+#define STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_
+
+#include <map>
+#include <string>
+
+#include "starboard/file.h"
+
+namespace starboard {
+namespace shared {
+namespace starboard {
+
+// Stores a map of internationalized strings for a particular language.
+// Initialized from a language-specific file in a simple, CSV-style format.
+class LocalizedStrings {
+ public:
+  explicit LocalizedStrings(const std::string& language);
+
+  // Gets a localized string.
+  std::string GetString(const std::string& id,
+                        const std::string& fallback) const;
+
+ private:
+  typedef std::map<std::string, std::string> StringMap;
+
+  // Loads the strings for a particular language.
+  // Returns true if successful, false otherwise.
+  bool LoadStrings(const std::string& language);
+
+  // Loads the strings from a specified file.
+  // Returns true if successful, false otherwise.
+  bool LoadStrings(SbFile file);
+
+  // Loads a single string.
+  // Returns true if successful, false otherwise.
+  bool LoadSingleString(const std::string& message);
+
+  StringMap strings_;
+};
+
+}  // namespace starboard
+}  // namespace shared
+}  // namespace starboard
+
+#endif  // STARBOARD_SHARED_STARBOARD_LOCALIZED_STRINGS_H_
diff --git a/src/starboard/shared/starboard/player/audio_renderer_internal.h b/src/starboard/shared/starboard/player/audio_renderer_internal.h
index d820049..cbc68c8 100644
--- a/src/starboard/shared/starboard/player/audio_renderer_internal.h
+++ b/src/starboard/shared/starboard/player/audio_renderer_internal.h
@@ -21,7 +21,6 @@
 #include "starboard/log.h"
 #include "starboard/media.h"
 #include "starboard/mutex.h"
-#include "starboard/shared/ffmpeg/ffmpeg_audio_decoder.h"
 #include "starboard/shared/internal_only.h"
 #include "starboard/shared/starboard/player/audio_decoder_internal.h"
 #include "starboard/shared/starboard/player/input_buffer_internal.h"
diff --git a/src/starboard/shared/stub/system_clear_platform_error.cc b/src/starboard/shared/stub/system_clear_platform_error.cc
new file mode 100644
index 0000000..2f13287
--- /dev/null
+++ b/src/starboard/shared/stub/system_clear_platform_error.cc
@@ -0,0 +1,19 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+void SbSystemClearPlatformError(SbSystemPlatformError handle) {
+  SB_UNREFERENCED_PARAMETER(handle);
+}
diff --git a/src/starboard/shared/stub/system_raise_platform_error.cc b/src/starboard/shared/stub/system_raise_platform_error.cc
new file mode 100644
index 0000000..4a80cb1
--- /dev/null
+++ b/src/starboard/shared/stub/system_raise_platform_error.cc
@@ -0,0 +1,42 @@
+// Copyright 2016 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "starboard/system.h"
+
+#include "starboard/log.h"
+
+SbSystemPlatformError SbSystemRaisePlatformError(
+    SbSystemPlatformErrorType type,
+    SbSystemPlatformErrorCallback callback,
+    void* user_data) {
+  SB_UNREFERENCED_PARAMETER(callback);
+  SB_UNREFERENCED_PARAMETER(user_data);
+  std::string message;
+  switch (type) {
+    case kSbSystemPlatformErrorTypeConnectionError:
+      message = "Connection error.";
+      break;
+    case kSbSystemPlatformErrorTypeUserSignedOut:
+      message = "User is not signed in.";
+      break;
+    case kSbSystemPlatformErrorTypeUserAgeRestricted:
+      message = "User is age restricted.";
+      break;
+    default:
+      message = "<unknown>";
+      break;
+  }
+  SB_DLOG(INFO) << "SbSystemRaisePlatformError: " << message;
+  return false;
+}
diff --git a/src/starboard/stub/configuration_public.h b/src/starboard/stub/configuration_public.h
index 4726791..744c7d5 100644
--- a/src/starboard/stub/configuration_public.h
+++ b/src/starboard/stub/configuration_public.h
@@ -293,6 +293,10 @@
 // working properly.
 #define SB_HAS_BILINEAR_FILTERING_SUPPORT 1
 
+// Indicates whether or not the given platform supports rendering of NV12
+// textures. These textures typically originate from video decoders.
+#define SB_HAS_NV12_TEXTURE_SUPPORT 0
+
 // --- Media Configuration ---------------------------------------------------
 
 // Specifies whether this platform has support for direct access to a decoder
diff --git a/src/starboard/stub/gyp_configuration.gypi b/src/starboard/stub/gyp_configuration.gypi
index c314126..24cabf4 100644
--- a/src/starboard/stub/gyp_configuration.gypi
+++ b/src/starboard/stub/gyp_configuration.gypi
@@ -13,16 +13,16 @@
 # limitations under the License.
 {
   'variables': {
-    'target_arch%': 'x64',
+    'target_arch': 'x64',
     'target_os': 'linux',
 
     'enable_webdriver': '1',
 
     # Use a stub rasterizer and graphical setup.
-    'rasterizer_type%': 'stub',
+    'rasterizer_type': 'stub',
 
     # No GL drivers available.
-    'gl_type%': 'none',
+    'gl_type': 'none',
 
     # This should have a default value in cobalt/base.gypi. See the comment
     # there for acceptable values for this variable.
diff --git a/src/starboard/stub/starboard_platform.gyp b/src/starboard/stub/starboard_platform.gyp
index 59fb9e4..1279317 100644
--- a/src/starboard/stub/starboard_platform.gyp
+++ b/src/starboard/stub/starboard_platform.gyp
@@ -170,6 +170,7 @@
         '<(DEPTH)/starboard/shared/stub/system_binary_search.cc',
         '<(DEPTH)/starboard/shared/stub/system_break_into_debugger.cc',
         '<(DEPTH)/starboard/shared/stub/system_clear_last_error.cc',
+        '<(DEPTH)/starboard/shared/stub/system_clear_platform_error.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_connection_type.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_device_type.cc',
         '<(DEPTH)/starboard/shared/stub/system_get_error_string.cc',
@@ -184,6 +185,7 @@
         '<(DEPTH)/starboard/shared/stub/system_get_total_memory.cc',
         '<(DEPTH)/starboard/shared/stub/system_has_capability.cc',
         '<(DEPTH)/starboard/shared/stub/system_is_debugger_attached.cc',
+        '<(DEPTH)/starboard/shared/stub/system_raise_platform_error.cc',
         '<(DEPTH)/starboard/shared/stub/system_request_stop.cc',
         '<(DEPTH)/starboard/shared/stub/system_sort.cc',
         '<(DEPTH)/starboard/shared/stub/system_symbolize.cc',
diff --git a/src/starboard/system.h b/src/starboard/system.h
index c1037c7..616d421 100644
--- a/src/starboard/system.h
+++ b/src/starboard/system.h
@@ -135,6 +135,85 @@
   kSbSystemCapabilityReversedEnterAndBack,
 } SbSystemCapabilityId;
 
+// Enumeration of possible values for the |type| parameter passed to  the
+// |SbSystemRaisePlatformError| function.
+typedef enum SbSystemPlatformErrorType {
+  // Cobalt received a network connection error, or a network disconnection
+  // event.
+  kSbSystemPlatformErrorTypeConnectionError,
+
+  // The current user is not signed in (e.g. to PSN network).
+  kSbSystemPlatformErrorTypeUserSignedOut,
+
+  // The current user does not meet the age requirements to use the app.
+  kSbSystemPlatformErrorTypeUserAgeRestricted
+} SbSystemPlatformErrorType;
+
+// Possible responses for |SbSystemPlatformErrorCallback|.
+typedef enum SbSystemPlatformErrorResponse {
+  kSbSystemPlatformErrorResponsePositive,
+  kSbSystemPlatformErrorResponseNegative,
+  kSbSystemPlatformErrorResponseCancel
+} SbSystemPlatformErrorResponse;
+
+// Type of callback function that may be called in response to an error
+// notification from |SbSystemRaisePlatformError|. |response| is a code to
+// indicate the user's response, e.g. if the platform raised a dialog to notify
+// the user of the error. |user_data| is the opaque pointer that was passed to
+// the call to |SbSystemRaisePlatformError|.
+typedef void (*SbSystemPlatformErrorCallback)(
+    SbSystemPlatformErrorResponse response,
+    void* user_data);
+
+// Private structure used to represent a raised platform error.
+typedef struct SbSystemPlatformErrorPrivate SbSystemPlatformErrorPrivate;
+
+// Opaque handle returned by |SbSystemRaisePlatformError| that can be passed
+// to |SbSystemClearPlatformError|.
+typedef SbSystemPlatformErrorPrivate* SbSystemPlatformError;
+
+// Well-defined value for an invalid |SbSystemPlatformError|.
+#define kSbSystemPlatformErrorInvalid (SbSystemPlatformError) NULL
+
+// Checks whether a |SbSystemPlatformError| is valid.
+static SB_C_INLINE bool SbSystemPlatformErrorIsValid(
+    SbSystemPlatformError handle) {
+  return handle != kSbSystemPlatformErrorInvalid;
+}
+
+// Called by Cobalt to notify the platform that an error has occurred in the
+// application that may have to be handled by the platform. It is expected the
+// platform will notify the user of the error, and provide interaction if
+// required, for example by showing a dialog.
+//
+// |type| is one of the enumerated types above to define the error; |callback|
+// is a function that may be called by the platform to let the caller know the
+// user has reacted to the error; |user_data| is an opaque pointer that the
+// platform should pass as an argument to the callback, if called.
+// Returns a handle that may be used in a subsequent call to
+// |SbClearPlatformError|, for example to programatically dismiss a dialog that
+// may have been raised in response to the error. The lifetime of
+// the object referenced by the handle is until the user reacts to the error
+// or the error is dismissed by a call to |SbSystemClearPlatformError|,
+// whichever happens first. If the platform cannot respond to the error, then
+// this function should return |kSbSystemPlatformErrorInvalid|.
+//
+// This function may be called from any thread; it is the responsibility of the
+// platform to decide how to handle an error received while a previous error is
+// still pending - if only one error can be handled at a time, then the
+// platform may queue the second error or ignore it by returning
+// |kSbSystemPlatformErrorInvalid|.
+SB_EXPORT SbSystemPlatformError
+SbSystemRaisePlatformError(SbSystemPlatformErrorType type,
+                           SbSystemPlatformErrorCallback callback,
+                           void* user_data);
+
+// Clears a platform error that was previously raised by a call to
+// |SbSystemRaisePlatformError|, specified by the handle that was returned by
+// that function. The platform may use this, for example, to close a dialog
+// that was opened in response to the error.
+SB_EXPORT void SbSystemClearPlatformError(SbSystemPlatformError handle);
+
 // Pointer to a function to compare two items, returning less than zero, zero,
 // or greater than zero depending on whether |a| is less than |b|, equal to |b|,
 // or greater than |b|, respectively (standard *cmp semantics).
diff --git a/src/starboard/user.h b/src/starboard/user.h
index aa7afc0..9dd1e1a 100644
--- a/src/starboard/user.h
+++ b/src/starboard/user.h
@@ -22,6 +22,7 @@
 #define STARBOARD_USER_H_
 
 #include "starboard/export.h"
+#include "starboard/time.h"
 #include "starboard/types.h"
 
 #ifdef __cplusplus
@@ -51,6 +52,27 @@
   kSbUserPropertyUserId,
 } SbUserPropertyId;
 
+#if SB_HAS(USER_APPLICATION_LINKING_SUPPORT)
+// Information about an application-specific authorization token.
+typedef struct SbUserApplicationTokenResults {
+  // The size of the buffer pointed to by |token_buffer|. Call
+  // SbUserMaxAuthenticationTokenSizeInBytes() to get an appropriate size.
+  // |token_buffer_size| must be set to a value greater than zero.
+  size_t token_buffer_size;
+
+  // Pointer to a buffer into which the token will be copied.
+  // |token_buffer| must not be NULL.
+  char* token_buffer;
+
+  // If true, |expiry| will be set. If false, the token never expires.
+  bool has_expiry;
+
+  // The absolute time that this token expires. It is valid to use the value of
+  // |expiry| only if |has_expiry| is true.
+  SbTime expiry;
+} SbUserApplicationTokenResults;
+#endif
+
 // Well-defined value for an invalid user.
 #define kSbUserInvalid (SbUser) NULL
 
@@ -95,6 +117,54 @@
 // user changed event being dispatched.
 SB_EXPORT void SbUserStartSignIn();
 
+#if SB_HAS(USER_APPLICATION_LINKING_SUPPORT)
+// Initiates a process to link |user| with a per-application authentication
+// token. On success, |out_token| is populated with the authentication token
+// and |out_expiry| is set to the number of seconds until the token expires. An
+// expiration of 0 indicates that the token never expires.
+// This call will block until the linking process is complete, which may involve
+// user input.
+// After this call completes successfully, subsequent calls to
+// SbUserRequestAuthenticationToken will return valid tokens.
+// Returns false if |user| is invalid, |token_results| is NULL,
+// |token_results.token_buffer| is NULL or if the token is larger than
+// |token_results.token_buffer_size|.
+// Returns true if process to link the token succeeded, and false if the process
+// failed for any reason including user cancellation.
+SB_EXPORT bool SbUserRequestApplicationLinking(
+    SbUser user,
+    SbUserApplicationTokenResults* token_results);
+
+// Remove the link between |user| and the per-application authentication token.
+// This call will block until the linking process is complete, which may involve
+// user input.
+// After this call completes successfully, subsequent calls to
+// SbUserRequestAuthenticationToken will fail.
+// Returns false if |user| is invalid.
+// Returns true if the process to unlink the token succeeded. Returns false if
+// the process failed for any reason including user cancellation.
+SB_EXPORT bool SbUserRequestApplicationUnlinking(SbUser user);
+
+// Requests a new per-application authentication token. On success, |out_token|
+// is populated with the authentication token and |out_expiry| is set to the
+// number of seconds until the token expires. An expiration of 0 indicates that
+// the token never expires.
+// This call will block until the token has been received.
+// Returns false if |user| is invalid, |out_token| or |out_expiration| are NULL,
+// or if the token is larger than |out_token_size|.
+// Returns false if the user account is not linked with an application. In this
+// case, SbUserRequestApplicationLinking should be called.
+// Returns true if process to link the token succeeded, and false if the process
+// failed for any reason including user cancellation.
+SB_EXPORT bool SbUserRequestAuthenticationToken(
+    SbUser user,
+    SbUserApplicationTokenResults* token_results);
+
+// Gets the maximum size of an authentication token as returned by
+// SbUserRequestApplicationLinking and SbUserRequestAuthenticationToken.
+SB_EXPORT size_t SbUserMaxAuthenticationTokenSizeInBytes();
+#endif  // SB_HAS(USER_APPLICATION_LINKING_SUPPORT)
+
 #ifdef __cplusplus
 }  // extern "C"
 #endif
diff --git a/src/third_party/libvpx/.mailmap b/src/third_party/libvpx/.mailmap
new file mode 100644
index 0000000..4672e5c
--- /dev/null
+++ b/src/third_party/libvpx/.mailmap
@@ -0,0 +1,32 @@
+Adrian Grange <agrange@google.com>
+Aâ„“ex Converse <aconverse@google.com>
+Aâ„“ex Converse <aconverse@google.com> <alex.converse@gmail.com>
+Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com>
+Alpha Lam <hclam@google.com> <hclam@chromium.org>
+Deb Mukherjee <debargha@google.com>
+Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com>
+Guillaume Martres <gmartres@google.com> <smarter3@gmail.com>
+Hangyu Kuang <hkuang@google.com>
+Hui Su <huisu@google.com>
+Jacky Chen <jackychen@google.com>
+Jim Bankoski <jimbankoski@google.com>
+Johann Koenig <johannkoenig@google.com>
+Johann Koenig <johannkoenig@google.com> <johann.koenig@duck.com>
+Johann Koenig <johannkoenig@google.com> <johann.koenig@gmail.com>
+John Koleszar <jkoleszar@google.com>
+Joshua Litt <joshualitt@google.com> <joshualitt@chromium.org>
+Marco Paniconi <marpan@google.com>
+Marco Paniconi <marpan@google.com> <marpan@chromium.org>
+Pascal Massimino <pascal.massimino@gmail.com>
+Paul Wilkins <paulwilkins@google.com>
+Ralph Giles <giles@xiph.org> <giles@entropywave.com>
+Ralph Giles <giles@xiph.org> <giles@mozilla.com>
+Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com>
+Sami Pietilä <samipietila@google.com>
+Tamar Levy <tamar.levy@intel.com>
+Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com>
+Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
+Timothy B. Terriberry <tterribe@xiph.org> Tim Terriberry <tterriberry@mozilla.com>
+Tom Finegan <tomfinegan@google.com>
+Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org>
+Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
diff --git a/src/third_party/libvpx/AUTHORS b/src/third_party/libvpx/AUTHORS
new file mode 100644
index 0000000..f89b677
--- /dev/null
+++ b/src/third_party/libvpx/AUTHORS
@@ -0,0 +1,134 @@
+# This file is automatically generated from the git commit history
+# by tools/gen_authors.sh.
+
+Aaron Watry <awatry@gmail.com>
+Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
+Adam Xu <adam@xuyaowu.com>
+Adrian Grange <agrange@google.com>
+Aâ„“ex Converse <aconverse@google.com>
+Ahmad Sharif <asharif@google.com>
+Alexander Voronov <avoronov@graphics.cs.msu.ru>
+Alexis Ballier <aballier@gentoo.org>
+Alok Ahuja <waveletcoeff@gmail.com>
+Alpha Lam <hclam@google.com>
+A.Mahfoodh <ab.mahfoodh@gmail.com>
+Ami Fischman <fischman@chromium.org>
+Andoni Morales Alastruey <ylatuya@gmail.com>
+Andres Mejia <mcitadel@gmail.com>
+Andrew Russell <anrussell@google.com>
+Angie Chiang <angiebird@google.com>
+Aron Rosenberg <arosenberg@logitech.com>
+Attila Nagy <attilanagy@google.com>
+Brion Vibber <bvibber@wikimedia.org>
+changjun.yang <changjun.yang@intel.com>
+Charles 'Buck' Krasic <ckrasic@google.com>
+chm <chm@rock-chips.com>
+Christian Duvivier <cduvivier@google.com>
+Daniel Kang <ddkang@google.com>
+Deb Mukherjee <debargha@google.com>
+Dim Temp <dimtemp0@gmail.com>
+Dmitry Kovalev <dkovalev@google.com>
+Dragan Mrdjan <dmrdjan@mips.com>
+Ed Baker <edward.baker@intel.com>
+Ehsan Akhgari <ehsan.akhgari@gmail.com>
+Erik Niemeyer <erik.a.niemeyer@intel.com>
+Fabio Pedretti <fabio.ped@libero.it>
+Frank Galligan <fgalligan@google.com>
+Fredrik Söderquist <fs@opera.com>
+Fritz Koenig <frkoenig@google.com>
+Gaute Strokkenes <gaute.strokkenes@broadcom.com>
+Geza Lore <gezalore@gmail.com>
+Ghislain MARY <ghislainmary2@gmail.com>
+Giuseppe Scrivano <gscrivano@gnu.org>
+Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
+Guillaume Martres <gmartres@google.com>
+Guillermo Ballester Valor <gbvalor@gmail.com>
+Hangyu Kuang <hkuang@google.com>
+Hanno Böck <hanno@hboeck.de>
+Henrik Lundin <hlundin@google.com>
+Hui Su <huisu@google.com>
+Ivan Maltz <ivanmaltz@google.com>
+Jacek Caban <cjacek@gmail.com>
+Jacky Chen <jackychen@google.com>
+James Berry <jamesberry@google.com>
+James Yu <james.yu@linaro.org>
+James Zern <jzern@google.com>
+Jan Gerber <j@mailb.org>
+Jan Kratochvil <jan.kratochvil@redhat.com>
+Janne Salonen <jsalonen@google.com>
+Jeff Faust <jfaust@google.com>
+Jeff Muizelaar <jmuizelaar@mozilla.com>
+Jeff Petkau <jpet@chromium.org>
+Jia Jia <jia.jia@linaro.org>
+Jim Bankoski <jimbankoski@google.com>
+Jingning Han <jingning@google.com>
+Joey Parrish <joeyparrish@google.com>
+Johann Koenig <johannkoenig@google.com>
+John Koleszar <jkoleszar@google.com>
+Johnny Klonaris <google@jawknee.com>
+John Stark <jhnstrk@gmail.com>
+Joshua Bleecher Snyder <josh@treelinelabs.com>
+Joshua Litt <joshualitt@google.com>
+Julia Robson <juliamrobson@gmail.com>
+Justin Clift <justin@salasaga.org>
+Justin Lebar <justin.lebar@gmail.com>
+KO Myung-Hun <komh@chollian.net>
+Lawrence Velázquez <larryv@macports.org>
+Lou Quillio <louquillio@google.com>
+Luca Barbato <lu_zero@gentoo.org>
+Makoto Kato <makoto.kt@gmail.com>
+Mans Rullgard <mans@mansr.com>
+Marco Paniconi <marpan@google.com>
+Mark Mentovai <mark@chromium.org>
+Martin Ettl <ettl.martin78@googlemail.com>
+Martin Storsjo <martin@martin.st>
+Matthew Heaney <matthewjheaney@chromium.org>
+Michael Kohler <michaelkohler@live.com>
+Mike Frysinger <vapier@chromium.org>
+Mike Hommey <mhommey@mozilla.com>
+Mikhal Shemer <mikhal@google.com>
+Minghai Shang <minghai@google.com>
+Morton Jonuschat <yabawock@gmail.com>
+Nico Weber <thakis@chromium.org>
+Parag Salasakar <img.mips1@gmail.com>
+Pascal Massimino <pascal.massimino@gmail.com>
+Patrik Westin <patrik.westin@gmail.com>
+Paul Wilkins <paulwilkins@google.com>
+Pavol Rusnak <stick@gk2.sk>
+Paweł Hajdan <phajdan@google.com>
+Pengchong Jin <pengchong@google.com>
+Peter de Rivaz <peter.derivaz@gmail.com>
+Philip Jägenstedt <philipj@opera.com>
+Priit Laes <plaes@plaes.org>
+Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
+Rafaël Carré <funman@videolan.org>
+Ralph Giles <giles@xiph.org>
+Rob Bradford <rob@linux.intel.com>
+Ronald S. Bultje <rsbultje@gmail.com>
+Rui Ueyama <ruiu@google.com>
+Sami Pietilä <samipietila@google.com>
+Scott Graham <scottmg@chromium.org>
+Scott LaVarnway <slavarnway@google.com>
+Sean McGovern <gseanmcg@gmail.com>
+Sergey Ulanov <sergeyu@chromium.org>
+Shimon Doodkin <helpmepro1@gmail.com>
+Shunyao Li <shunyaoli@google.com>
+Stefan Holmer <holmer@google.com>
+Suman Sunkara <sunkaras@google.com>
+Taekhyun Kim <takim@nvidia.com>
+Takanori MATSUURA <t.matsuu@gmail.com>
+Tamar Levy <tamar.levy@intel.com>
+Tao Bai <michaelbai@chromium.org>
+Tero Rintaluoma <teror@google.com>
+Thijs Vermeir <thijsvermeir@gmail.com>
+Tim Kopp <tkopp@google.com>
+Timothy B. Terriberry <tterribe@xiph.org>
+Tom Finegan <tomfinegan@google.com>
+Vignesh Venkatasubramanian <vigneshv@google.com>
+Yaowu Xu <yaowu@google.com>
+Yongzhe Wang <yongzhe@google.com>
+Yunqing Wang <yunqingwang@google.com>
+Zoe Liu <zoeliu@google.com>
+Google Inc.
+The Mozilla Foundation
+The Xiph.Org Foundation
diff --git a/src/third_party/libvpx/CHANGELOG b/src/third_party/libvpx/CHANGELOG
new file mode 100644
index 0000000..7db420e
--- /dev/null
+++ b/src/third_party/libvpx/CHANGELOG
@@ -0,0 +1,628 @@
+Next Release
+  - Incompatible changes:
+    The VP9 encoder's default keyframe interval changed to 128 from 9999.
+
+2015-11-09 v1.5.0 "Javan Whistling Duck"
+  This release improves upon the VP9 encoder and speeds up the encoding and
+  decoding processes.
+
+  - Upgrading:
+    This release is ABI incompatible with 1.4.0. It drops deprecated VP8
+    controls and adds a variety of VP9 controls for testing.
+
+    The vpxenc utility now prefers VP9 by default.
+
+  - Enhancements:
+    Faster VP9 encoding and decoding
+    Smaller library size by combining functions used by VP8 and VP9
+
+  - Bug Fixes:
+    A variety of fuzzing issues
+
+2015-04-03 v1.4.0 "Indian Runner Duck"
+  This release includes significant improvements to the VP9 codec.
+
+  - Upgrading:
+    This release is ABI incompatible with 1.3.0. It drops the compatibility
+    layer, requiring VPX_IMG_FMT_* instead of IMG_FMT_*, and adds several codec
+    controls for VP9.
+
+  - Enhancements:
+    Faster VP9 encoding and decoding
+    Multithreaded VP9 decoding (tile and frame-based)
+    Multithreaded VP9 encoding - on by default
+    YUV 4:2:2 and 4:4:4 support in VP9
+    10 and 12bit support in VP9
+    64bit ARM support by replacing ARM assembly with intrinsics
+
+  - Bug Fixes:
+    Fixes a VP9 bitstream issue in Profile 1. This only affected non-YUV 4:2:0
+    files.
+
+  - Known Issues:
+    Frame Parallel decoding fails for segmented and non-420 files.
+
+2013-11-15 v1.3.0 "Forest"
+  This release introduces the VP9 codec in a backward-compatible way.
+  All existing users of VP8 can continue to use the library without
+  modification. However, some VP8 options do not map to VP9 in the same manner.
+
+  The VP9 encoder in this release is not feature complete. Users interested in
+  the encoder are advised to use the git master branch and discuss issues on
+  libvpx mailing lists.
+
+  - Upgrading:
+    This release is ABI and API compatible with Duclair (v1.0.0). Users
+    of older releases should refer to the Upgrading notes in this document
+    for that release.
+
+  - Enhancements:
+      Get rid of bashisms in the main build scripts
+      Added usage info on command line options
+      Add lossless compression mode
+      Dll build of libvpx
+      Add additional Mac OS X targets: 10.7, 10.8 and 10.9 (darwin11-13)
+      Add option to disable documentation
+      configure: add --enable-external-build support
+      make: support V=1 as short form of verbose=yes
+      configure: support mingw-w64
+      configure: support hardfloat armv7 CHOSTS
+      configure: add support for android x86
+      Add estimated completion time to vpxenc
+      Don't exit on decode errors in vpxenc
+      vpxenc: support scaling prior to encoding
+      vpxdec: support scaling output
+      vpxenc: improve progress indicators with --skip
+      msvs: Don't link to winmm.lib
+      Add a new script for producing vcxproj files
+      Produce Visual Studio 10 and 11 project files
+      Produce Windows Phone project files
+      msvs-build: use msbuild for vs >= 2005
+      configure: default configure log to config.log
+      Add encoding option --static-thresh
+
+  - Speed:
+      Miscellaneous speed optimizations for VP8 and VP9.
+
+  - Quality:
+      In general, quality is consistent with the Eider release.
+
+  - Bug Fixes:
+      This release represents approximately a year of engineering effort,
+      and contains multiple bug fixes. Please refer to git history for details.
+
+
+2012-12-21 v1.2.0
+  This release acts as a checkpoint for a large amount of internal refactoring
+  and testing. It also contains a number of small bugfixes, so all users are
+  encouraged to upgrade.
+
+  - Upgrading:
+    This release is ABI and API compatible with Duclair (v1.0.0). Users
+    of older releases should refer to the Upgrading notes in this
+    document for that release.
+
+  - Enhancements:
+      VP8 optimizations for MIPS dspr2
+      vpxenc: add -quiet option
+
+  - Speed:
+      Encoder and decoder speed is consistent with the Eider release.
+
+  - Quality:
+      In general, quality is consistent with the Eider release.
+
+      Minor tweaks to ARNR filtering
+      Minor improvements to real time encoding with multiple temporal layers
+
+  - Bug Fixes:
+      Fixes multithreaded encoder race condition in loopfilter
+      Fixes multi-resolution threaded encoding
+      Fix potential encoder dead-lock after picture resize
+
+
+2012-05-09 v1.1.0 "Eider"
+  This introduces a number of enhancements, mostly focused on real-time
+  encoding. In addition, it fixes a decoder bug (first introduced in
+  Duclair) so all users of that release are encouraged to upgrade.
+
+  - Upgrading:
+    This release is ABI and API compatible with Duclair (v1.0.0). Users
+    of older releases should refer to the Upgrading notes in this
+    document for that release.
+
+    This release introduces a new temporal denoiser, controlled by the
+    VP8E_SET_NOISE_SENSITIVITY control. The temporal denoiser does not
+    currently take a strength parameter, so the control is effectively
+    a boolean - zero (off) or non-zero (on). For compatibility with
+    existing applications, the values accepted are the same as those
+    for the spatial denoiser (0-6). The temporal denoiser is enabled
+    by default, and the older spatial denoiser may be restored by
+    configuring with --disable-temporal-denoising. The temporal denoiser
+    is more computationally intensive than the spatial one.
+
+    This release removes support for a legacy, decode only API that was
+    supported, but deprecated, at the initial release of libvpx
+    (v0.9.0). This is not expected to have any impact. If you are
+    impacted, you can apply a reversion to commit 2bf8fb58 locally.
+    Please update to the latest libvpx API if you are affected.
+
+  - Enhancements:
+      Adds a motion compensated temporal denoiser to the encoder, which
+      gives higher quality than the older spatial denoiser. (See above
+      for notes on upgrading).
+
+      In addition, support for new compilers and platforms were added,
+      including:
+        improved support for XCode
+        Android x86 NDK build
+        OS/2 support
+        SunCC support
+
+      Changing resolution with vpx_codec_enc_config_set() is now
+      supported. Previously, reinitializing the codec was required to
+      change the input resolution.
+
+      The vpxenc application has initial support for producing multiple
+      encodes from the same input in one call. Resizing is not yet
+      supported, but varying other codec parameters is. Use -- to
+      delineate output streams. Options persist from one stream to the
+      next.
+
+      Also, the vpxenc application will now use a keyframe interval of
+      5 seconds by default. Use the --kf-max-dist option to override.
+
+  - Speed:
+      Decoder performance improved 2.5% versus Duclair. Encoder speed is
+      consistent with Duclair for most material. Two pass encoding of
+      slideshow-like material will see significant improvements.
+
+      Large realtime encoding speed gains at a small quality expense are
+      possible by configuring the on-the-fly bitpacking experiment with
+      --enable-onthefly-bitpacking. Realtime encoder can be up to 13%
+      faster (ARM) depending on the number of threads and bitrate
+      settings. This technique sees constant gain over the 5-16 speed
+      range. For VC style input the loss seen is up to 0.2dB. See commit
+      52cf4dca for further details.
+
+  - Quality:
+      On the whole, quality is consistent with the Duclair release. Some
+      tweaks:
+
+        Reduced blockiness in easy sections by applying a penalty to
+        intra modes.
+
+        Improved quality of static sections (like slideshows) with
+        two pass encoding.
+
+        Improved keyframe sizing with multiple temporal layers
+
+  - Bug Fixes:
+      Corrected alt-ref contribution to frame rate for visible updates
+      to the alt-ref buffer. This affected applications making manual
+      usage of the frame reference flags, or temporal layers.
+
+      Additional constraints were added to disable multi-frame quality
+      enhancement (MFQE) in sections of the frame where there is motion.
+      (#392)
+
+      Fixed corruption issues when vpx_codec_enc_config_set() was called
+      with spatial resampling enabled.
+
+      Fixed a decoder error introduced in Duclair where the segmentation
+      map was not being reinitialized on keyframes (#378)
+
+
+2012-01-27 v1.0.0 "Duclair"
+  Our fourth named release, focused on performance and features related to
+  real-time encoding. It also fixes a decoder crash bug introduced in
+  v0.9.7, so all users of that release are encouraged to upgrade.
+
+  - Upgrading:
+      This release is ABI incompatible with prior releases of libvpx, so the
+      "major" version number has been bumped to 1. You must recompile your
+      applications against the latest version of the libvpx headers. The
+      API remains compatible, and this should not require code changes in most
+      applications.
+
+  - Enhancements:
+      This release introduces several substantial new features to the encoder,
+      of particular interest to real time streaming applications.
+
+      Temporal scalability allows the encoder to produce a stream that can
+      be decimated to different frame rates, with independent rate targetting
+      for each substream.
+
+      Multiframe quality enhancement postprocessing can make visual quality
+      more consistent in the presence of frames that are substantially
+      different quality than the surrounding frames, as in the temporal
+      scalability case and in some forced keyframe scenarios.
+
+      Multiple-resolution encoding support allows the encoding of the
+      same content at different resolutions faster than encoding them
+      separately.
+
+  - Speed:
+      Optimization targets for this release included the decoder and the real-
+      time modes of the encoder. Decoder speed on x86 has improved 10.5% with
+      this release. Encoder improvements followed a curve where speeds 1-3
+      improved 4.0%-1.5%, speeds 4-8 improved <1%, and speeds 9-16 improved
+      1.5% to 10.5%, respectively. "Best" mode speed is consistent with the
+      Cayuga release.
+
+  - Quality:
+      Encoder quality in the single stream case is consistent with the Cayuga
+      release.
+
+  - Bug Fixes:
+      This release fixes an OOB read decoder crash bug present in v0.9.7
+      related to the clamping of motion vectors in SPLITMV blocks. This
+      behavior could be triggered by corrupt input or by starting
+      decoding from a P-frame.
+
+
+2011-08-15 v0.9.7-p1 "Cayuga" patch 1
+  This is an incremental bugfix release against Cayuga. All users of that
+  release are strongly encouraged to upgrade.
+
+    - Fix potential OOB reads (cdae03a)
+
+          An unbounded out of bounds read was discovered when the
+          decoder was requested to perform error concealment (new in
+          Cayuga) given a frame with corrupt partition sizes.
+
+          A bounded out of bounds read was discovered affecting all
+          versions of libvpx. Given an multipartition input frame that
+          is truncated between the mode/mv partition and the first
+          residiual paritition (in the block of partition offsets), up
+          to 3 extra bytes could have been read from the source buffer.
+          The code will not take any action regardless of the contents
+          of these undefined bytes, as the truncated buffer is detected
+          immediately following the read based on the calculated
+          starting position of the coefficient partition.
+
+    - Fix potential error concealment crash when the very first frame
+      is missing or corrupt (a609be5)
+
+    - Fix significant artifacts in error concealment (a4c2211, 99d870a)
+
+    - Revert 1-pass CBR rate control changes (e961317)
+      Further testing showed this change produced undesirable visual
+      artifacts, rolling back for now.
+
+
+2011-08-02 v0.9.7 "Cayuga"
+  Our third named release, focused on a faster, higher quality, encoder.
+
+  - Upgrading:
+    This release is backwards compatible with Aylesbury (v0.9.5) and
+    Bali (v0.9.6). Users of older releases should refer to the Upgrading
+    notes in this document for that release.
+
+  - Enhancements:
+          Stereo 3D format support for vpxenc
+          Runtime detection of available processor cores.
+          Allow specifying --end-usage by enum name
+          vpxdec: test for frame corruption
+          vpxenc: add quantizer histogram display
+          vpxenc: add rate histogram display
+          Set VPX_FRAME_IS_DROPPABLE
+          update configure for ios sdk 4.3
+          Avoid text relocations in ARM vp8 decoder
+          Generate a vpx.pc file for pkg-config.
+          New ways of passing encoded data between encoder and decoder.
+
+  - Speed:
+      This release includes across-the-board speed improvements to the
+      encoder. On x86, these measure at approximately 11.5% in Best mode,
+      21.5% in Good mode (speed 0), and 22.5% in Realtime mode (speed 6).
+      On ARM Cortex A9 with Neon extensions, real-time encoding of video
+      telephony content is 35% faster than Bali on single core and 48%
+      faster on multi-core. On the NVidia Tegra2 platform, real time
+      encoding is 40% faster than Bali.
+
+      Decoder speed was not a priority for this release, but improved
+      approximately 8.4% on x86.
+
+          Reduce motion vector search on alt-ref frame.
+          Encoder loopfilter running in its own thread
+          Reworked loopfilter to precalculate more parameters
+          SSE2/SSSE3 optimizations for build_predictors_mbuv{,_s}().
+          Make hor UV predict ~2x faster (73 vs 132 cycles) using SSSE3.
+          Removed redundant checks
+          Reduced structure sizes
+          utilize preload in ARMv6 MC/LPF/Copy routines
+          ARM optimized quantization, dfct, variance, subtract
+          Increase chrow row alignment to 16 bytes.
+          disable trellis optimization for first pass
+          Write SSSE3 sub-pixel filter function
+          Improve SSE2 half-pixel filter funtions
+          Add vp8_sub_pixel_variance16x8_ssse3 function
+          Reduce unnecessary distortion computation
+          Use diamond search to replace full search
+          Preload reference area in sub-pixel motion search (real-time mode)
+
+  - Quality:
+      This release focused primarily on one-pass use cases, including
+      video conferencing. Low latency data rate control was significantly
+      improved, improving streamability over bandwidth constrained links.
+      Added support for error concealment, allowing frames to maintain
+      visual quality in the presence of substantial packet loss.
+
+          Add rc_max_intra_bitrate_pct control
+          Limit size of initial keyframe in one-pass.
+          Improve framerate adaptation
+          Improved 1-pass CBR rate control
+          Improved KF insertion after fades to still.
+          Improved key frame detection.
+          Improved activity masking (lower PSNR impact for same SSIM boost)
+          Improved interaction between GF and ARFs
+          Adding error-concealment to the decoder.
+          Adding support for independent partitions
+          Adjusted rate-distortion constants
+
+
+  - Bug Fixes:
+          Removed firstpass motion map
+          Fix parallel make install
+          Fix multithreaded encoding for 1 MB wide frame
+          Fixed iwalsh_neon build problems with RVDS4.1
+          Fix semaphore emulation, spin-wait intrinsics on Windows
+          Fix build with xcode4 and simplify GLOBAL.
+          Mark ARM asm objects as allowing a non-executable stack.
+          Fix vpxenc encoding incorrect webm file header on big endian
+
+
+2011-03-07 v0.9.6 "Bali"
+  Our second named release, focused on a faster, higher quality, encoder.
+
+  - Upgrading:
+    This release is backwards compatible with Aylesbury (v0.9.5). Users
+    of older releases should refer to the Upgrading notes in this
+    document for that release.
+
+  - Enhancements:
+      vpxenc --psnr shows a summary when encode completes
+      --tune=ssim option to enable activity masking
+      improved postproc visualizations for development
+      updated support for Apple iOS to SDK 4.2
+      query decoder to determine which reference frames were updated
+      implemented error tracking in the decoder
+      fix pipe support on windows
+
+  - Speed:
+      Primary focus was on good quality mode, speed 0. Average improvement
+      on x86 about 40%, up to 100% on user-generated content at that speed.
+      Best quality mode speed improved 35%, and realtime speed 10-20%. This
+      release also saw significant improvement in realtime encoding speed
+      on ARM platforms.
+
+        Improved encoder threading
+        Dont pick encoder filter level when loopfilter is disabled.
+        Avoid double copying of key frames into alt and golden buffer
+        FDCT optimizations.
+        x86 sse2 temporal filter
+        SSSE3 version of fast quantizer
+        vp8_rd_pick_best_mbsegmentation code restructure
+        Adjusted breakout RD for SPLITMV
+        Changed segmentation check order
+        Improved rd_pick_intra4x4block
+        Adds armv6 optimized variance calculation
+        ARMv6 optimized sad16x16
+        ARMv6 optimized half pixel variance calculations
+        Full search SAD function optimization in SSE4.1
+        Improve MV prediction accuracy to achieve performance gain
+        Improve MV prediction in vp8_pick_inter_mode() for speed>3
+
+  - Quality:
+      Best quality mode improved PSNR 6.3%, and SSIM 6.1%. This release
+      also includes support for "activity masking," which greatly improves
+      SSIM at the expense of PSNR. For now, this feature is available with
+      the --tune=ssim option. Further experimentation in this area
+      is ongoing. This release also introduces a new rate control mode
+      called "CQ," which changes the allocation of bits within a clip to
+      the sections where they will have the most visual impact.
+
+        Tuning for the more exact quantizer.
+        Relax rate control for last few frames
+        CQ Mode
+        Limit key frame quantizer for forced key frames.
+        KF/GF Pulsing
+        Add simple version of activity masking.
+        make rdmult adaptive for intra in quantizer RDO
+        cap the best quantizer for 2nd order DC
+        change the threshold of DC check for encode breakout
+
+  - Bug Fixes:
+      Fix crash on Sparc Solaris.
+      Fix counter of fixed keyframe distance
+      ARNR filter pointer update bug fix
+      Fixed use of motion percentage in KF/GF group calc
+      Changed condition for using RD in Intra Mode
+      Fix encoder real-time only configuration.
+      Fix ARM encoder crash with multiple token partitions
+      Fixed bug first cluster timecode of webm file is wrong.
+      Fixed various encoder bugs with odd-sized images
+      vp8e_get_preview fixed when spatial resampling enabled
+      quantizer: fix assertion in fast quantizer path
+      Allocate source buffers to be multiples of 16
+      Fix for manual Golden frame frequency
+      Fix drastic undershoot in long form content
+
+
+2010-10-28 v0.9.5 "Aylesbury"
+  Our first named release, focused on a faster decoder, and a better encoder.
+
+  - Upgrading:
+    This release incorporates backwards-incompatible changes to the
+    ivfenc and ivfdec tools. These tools are now called vpxenc and vpxdec.
+
+    vpxdec
+      * the -q (quiet) option has been removed, and replaced with
+        -v (verbose). the output is quiet by default. Use -v to see
+        the version number of the binary.
+
+      * The default behavior is now to write output to a single file
+        instead of individual frames. The -y option has been removed.
+        Y4M output is the default.
+
+      * For raw I420/YV12 output instead of Y4M, the --i420 or --yv12
+        options must be specified.
+
+          $ ivfdec -o OUTPUT INPUT
+          $ vpxdec --i420 -o OUTPUT INPUT
+
+      * If an output file is not specified, the default is to write
+        Y4M to stdout. This makes piping more natural.
+
+          $ ivfdec -y -o - INPUT | ...
+          $ vpxdec INPUT | ...
+
+      * The output file has additional flexibility for formatting the
+        filename. It supports escape characters for constructing a
+        filename from the width, height, and sequence number. This
+        replaces the -p option. To get the equivalent:
+
+          $ ivfdec -p frame INPUT
+          $ vpxdec --i420 -o frame-%wx%h-%4.i420 INPUT
+
+    vpxenc
+      * The output file must be specified with -o, rather than as the
+        last argument.
+
+          $ ivfenc <options> INPUT OUTPUT
+          $ vpxenc <options> -o OUTPUT INPUT
+
+      * The output defaults to webm. To get IVF output, use the --ivf
+        option.
+
+          $ ivfenc <options> INPUT OUTPUT.ivf
+          $ vpxenc <options> -o OUTPUT.ivf --ivf INPUT
+
+
+  - Enhancements:
+      ivfenc and ivfdec have been renamed to vpxenc, vpxdec.
+      vpxdec supports .webm input
+      vpxdec writes .y4m by default
+      vpxenc writes .webm output by default
+      vpxenc --psnr now shows the average/overall PSNR at the end
+      ARM platforms now support runtime cpu detection
+      vpxdec visualizations added for motion vectors, block modes, references
+      vpxdec now silent by default
+      vpxdec --progress shows frame-by-frame timing information
+      vpxenc supports the distinction between --fps and --timebase
+      NASM is now a supported assembler
+      configure: enable PIC for shared libs by default
+      configure: add --enable-small
+      configure: support for ppc32-linux-gcc
+      configure: support for sparc-solaris-gcc
+
+  - Bugs:
+      Improve handling of invalid frames
+      Fix valgrind errors in the NEON loop filters.
+      Fix loopfilter delta zero transitions
+      Fix valgrind errors in vp8_sixtap_predict8x4_armv6().
+      Build fixes for darwin-icc
+
+  - Speed:
+      20-40% (average 28%) improvement in libvpx decoder speed,
+      including:
+        Rewrite vp8_short_walsh4x4_sse2()
+        Optimizations on the loopfilters.
+        Miscellaneous improvements for Atom
+        Add 4-tap version of 2nd-pass ARMv6 MC filter.
+        Improved multithread utilization
+        Better instruction choices on x86
+        reorder data to use wider instructions
+        Update NEON wide idcts
+        Make block access to frame buffer sequential
+        Improved subset block search
+        Bilinear subpixel optimizations for ssse3.
+        Decrease memory footprint
+
+      Encoder speed improvements (percentage gain not measured):
+        Skip unnecessary search of identical frames
+        Add SSE2 subtract functions
+        Improve bounds checking in vp8_diamond_search_sadx4()
+        Added vp8_fast_quantize_b_sse2
+
+  - Quality:
+      Over 7% overall PSNR improvement (6.3% SSIM) in "best" quality
+      encoding mode, and up to 60% improvement on very noisy, still
+      or slow moving source video
+
+        Motion compensated temporal filter for Alt-Ref Noise Reduction
+        Improved use of trellis quantization on 2nd order Y blocks
+        Tune effect of motion on KF/GF boost in two pass
+        Allow coefficient optimization for good quality speed 0.
+        Improved control of active min quantizer for two pass.
+        Enable ARFs for non-lagged compress
+
+2010-09-02 v0.9.2
+  - Enhancements:
+      Disable frame dropping by default
+      Improved multithreaded performance
+      Improved Force Key Frame Behaviour
+      Increased rate control buffer level precision
+      Fix bug in 1st pass motion compensation
+      ivfenc: correct fixed kf interval, --disable-kf
+  - Speed:
+      Changed above and left context data layout
+      Rework idct calling structure.
+      Removed unnecessary MB_MODE_INFO copies
+      x86: SSSE3 sixtap prediction
+      Reworked IDCT to include reconstruction (add) step
+      Swap alt/gold/new/last frame buffer ptrs instead of copying.
+      Improve SSE2 loopfilter functions
+      Change bitreader to use a larger window.
+      Avoid loopfilter reinitialization when possible
+  - Quality:
+      Normalize quantizer's zero bin and rounding factors
+      Add trellis quantization.
+      Make the quantizer exact.
+      Updates to ARNR filtering algorithm
+      Fix breakout thresh computation for golden & AltRef frames
+      Redo the forward 4x4 dct
+      Improve the accuracy of forward walsh-hadamard transform
+      Further adjustment of RD behaviour with Q and Zbin.
+  - Build System:
+      Allow linking of libs built with MinGW to MSVC
+      Fix target auto-detection on mingw32
+      Allow --cpu= to work for x86.
+      configure: pass original arguments through to make dist
+      Fix builds without runtime CPU detection
+      msvs: fix install of codec sources
+      msvs: Change devenv.com command line for better msys support
+      msvs: Add vs9 targets.
+      Add x86_64-linux-icc target
+  - Bugs:
+      Potential crashes on older MinGW builds
+      Fix two-pass framrate for Y4M input.
+      Fixed simple loop filter, other crashes on ARM v6
+      arm: fix missing dependency with --enable-shared
+      configure: support directories containing .o
+      Replace pinsrw (SSE) with MMX instructions
+      apple: include proper mach primatives
+      Fixed rate control bug with long key frame interval.
+      Fix DSO link errors on x86-64 when not using a version script
+      Fixed buffer selection for UV in AltRef filtering
+
+
+2010-06-17 v0.9.1
+  - Enhancements:
+      * ivfenc/ivfdec now support YUV4MPEG2 input and pipe I/O
+      * Speed optimizations
+  - Bugfixes:
+      * Rate control
+      * Prevent out-of-bounds accesses on invalid data
+  - Build system updates:
+      * Detect toolchain to be used automatically for native builds
+      * Support building shared libraries
+      * Better autotools emulation (--prefix, --libdir, DESTDIR)
+  - Updated LICENSE
+      * http://webmproject.blogspot.com/2010/06/changes-to-webm-open-source-license.html
+
+
+2010-05-18 v0.9.0
+  - Initial open source release. Welcome to WebM and VP8!
+
diff --git a/src/third_party/libvpx/LICENSE b/src/third_party/libvpx/LICENSE
new file mode 100644
index 0000000..1ce4434
--- /dev/null
+++ b/src/third_party/libvpx/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2010, The WebM Project authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in
+    the documentation and/or other materials provided with the
+    distribution.
+
+  * Neither the name of Google, nor the WebM Project, nor the names
+    of its contributors may be used to endorse or promote products
+    derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/src/third_party/libvpx/PATENTS b/src/third_party/libvpx/PATENTS
new file mode 100644
index 0000000..caedf60
--- /dev/null
+++ b/src/third_party/libvpx/PATENTS
@@ -0,0 +1,23 @@
+Additional IP Rights Grant (Patents)
+------------------------------------
+
+"These implementations" means the copyrightable works that implement the WebM
+codecs distributed by Google as part of the WebM Project.
+
+Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
+royalty-free, irrevocable (except as stated in this section) patent license to
+make, have made, use, offer to sell, sell, import, transfer, and otherwise
+run, modify and propagate the contents of these implementations of WebM, where
+such license applies only to those patent claims, both currently owned by
+Google and acquired in the future, licensable by Google that are necessarily
+infringed by these implementations of WebM. This grant does not include claims
+that would be infringed only as a consequence of further modification of these
+implementations. If you or your agent or exclusive licensee institute or order
+or agree to the institution of patent litigation or any other patent
+enforcement activity against any entity (including a cross-claim or
+counterclaim in a lawsuit) alleging that any of these implementations of WebM
+or any code incorporated within any of these implementations of WebM
+constitute direct or contributory patent infringement, or inducement of
+patent infringement, then any patent rights granted to you under this License
+for these implementations of WebM shall terminate as of the date such
+litigation is filed.
diff --git a/src/third_party/libvpx/README b/src/third_party/libvpx/README
new file mode 100644
index 0000000..29072b9
--- /dev/null
+++ b/src/third_party/libvpx/README
@@ -0,0 +1,138 @@
+README - 23 March 2015
+
+Welcome to the WebM VP8/VP9 Codec SDK!
+
+COMPILING THE APPLICATIONS/LIBRARIES:
+  The build system used is similar to autotools. Building generally consists of
+  "configuring" with your desired build options, then using GNU make to build
+  the application.
+
+  1. Prerequisites
+
+    * All x86 targets require the Yasm[1] assembler be installed.
+    * All Windows builds require that Cygwin[2] be installed.
+    * Building the documentation requires Doxygen[3]. If you do not
+      have this package, the install-docs option will be disabled.
+    * Downloading the data for the unit tests requires curl[4] and sha1sum.
+      sha1sum is provided via the GNU coreutils, installed by default on
+      many *nix platforms, as well as MinGW and Cygwin. If coreutils is not
+      available, a compatible version of sha1sum can be built from
+      source[5]. These requirements are optional if not running the unit
+      tests.
+
+    [1]: http://www.tortall.net/projects/yasm
+    [2]: http://www.cygwin.com
+    [3]: http://www.doxygen.org
+    [4]: http://curl.haxx.se
+    [5]: http://www.microbrew.org/tools/md5sha1sum/
+
+  2. Out-of-tree builds
+  Out of tree builds are a supported method of building the application. For
+  an out of tree build, the source tree is kept separate from the object
+  files produced during compilation. For instance:
+
+    $ mkdir build
+    $ cd build
+    $ ../libvpx/configure <options>
+    $ make
+
+  3. Configuration options
+  The 'configure' script supports a number of options. The --help option can be
+  used to get a list of supported options:
+    $ ../libvpx/configure --help
+
+  4. Cross development
+  For cross development, the most notable option is the --target option. The
+  most up-to-date list of supported targets can be found at the bottom of the
+  --help output of the configure script. As of this writing, the list of
+  available targets is:
+
+    armv6-linux-rvct
+    armv6-linux-gcc
+    armv6-none-rvct
+    arm64-darwin-gcc
+    armv7-android-gcc
+    armv7-darwin-gcc
+    armv7-linux-rvct
+    armv7-linux-gcc
+    armv7-none-rvct
+    armv7-win32-vs11
+    armv7-win32-vs12
+    armv7-win32-vs14
+    armv7s-darwin-gcc
+    mips32-linux-gcc
+    mips64-linux-gcc
+    sparc-solaris-gcc
+    x86-android-gcc
+    x86-darwin8-gcc
+    x86-darwin8-icc
+    x86-darwin9-gcc
+    x86-darwin9-icc
+    x86-darwin10-gcc
+    x86-darwin11-gcc
+    x86-darwin12-gcc
+    x86-darwin13-gcc
+    x86-darwin14-gcc
+    x86-iphonesimulator-gcc
+    x86-linux-gcc
+    x86-linux-icc
+    x86-os2-gcc
+    x86-solaris-gcc
+    x86-win32-gcc
+    x86-win32-vs7
+    x86-win32-vs8
+    x86-win32-vs9
+    x86-win32-vs10
+    x86-win32-vs11
+    x86-win32-vs12
+    x86-win32-vs14
+    x86_64-android-gcc
+    x86_64-darwin9-gcc
+    x86_64-darwin10-gcc
+    x86_64-darwin11-gcc
+    x86_64-darwin12-gcc
+    x86_64-darwin13-gcc
+    x86_64-darwin14-gcc
+    x86_64-iphonesimulator-gcc
+    x86_64-linux-gcc
+    x86_64-linux-icc
+    x86_64-solaris-gcc
+    x86_64-win64-gcc
+    x86_64-win64-vs8
+    x86_64-win64-vs9
+    x86_64-win64-vs10
+    x86_64-win64-vs11
+    x86_64-win64-vs12
+    x86_64-win64-vs14
+    generic-gnu
+
+  The generic-gnu target, in conjunction with the CROSS environment variable,
+  can be used to cross compile architectures that aren't explicitly listed, if
+  the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains
+  will likely work as well. For instance, to build using the mipsel-linux-uclibc
+  toolchain, the following command could be used (note, POSIX SH syntax, adapt
+  to your shell as necessary):
+
+    $ CROSS=mipsel-linux-uclibc- ../libvpx/configure
+
+  In addition, the executables to be invoked can be overridden by specifying the
+  environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
+  passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
+
+  5. Configuration errors
+  If the configuration step fails, the first step is to look in the error log.
+  This defaults to config.log. This should give a good indication of what went
+  wrong. If not, contact us for support.
+
+VP8/VP9 TEST VECTORS:
+  The test vectors can be downloaded and verified using the build system after
+  running configure. To specify an alternate directory the
+  LIBVPX_TEST_DATA_PATH environment variable can be used.
+
+  $ ./configure --enable-unit-tests
+  $ LIBVPX_TEST_DATA_PATH=../libvpx-test-data make testdata
+
+SUPPORT
+  This library is an open source project supported by its community. Please
+  please email webm-discuss@webmproject.org for help.
+
diff --git a/src/third_party/libvpx/README.lbshell b/src/third_party/libvpx/README.lbshell
new file mode 100644
index 0000000..9e83ef4
--- /dev/null
+++ b/src/third_party/libvpx/README.lbshell
@@ -0,0 +1,15 @@
+Name: libvpx
+URL: http://www.webmproject.org
+Version: v1.3.0
+License: BSD
+License File: source/libvpx/LICENSE
+Security Critical: yes
+
+Date: Fri Jan 9 2015
+Branch: master
+Commit: ccffe318ffc90ae584c33e254b3a35e9142ecc20
+
+This is the version used in the public Chrome release.
+See: [chromium] //src/third_party/libvpx/README.chromium
+
+See platforms/ps4 for Steel-specific details.
diff --git a/src/third_party/libvpx/args.c b/src/third_party/libvpx/args.c
new file mode 100644
index 0000000..14b0310
--- /dev/null
+++ b/src/third_party/libvpx/args.c
@@ -0,0 +1,236 @@
+/*
+ *  Copyright (c) 2010 The WebM 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 <string.h>
+#include <limits.h>
+#include "args.h"
+
+#include "vpx_ports/msvc.h"
+
+#if defined(__GNUC__) && __GNUC__
+extern void die(const char *fmt, ...) __attribute__((noreturn));
+#else
+extern void die(const char *fmt, ...);
+#endif
+
+
+struct arg arg_init(char **argv) {
+  struct arg a;
+
+  a.argv      = argv;
+  a.argv_step = 1;
+  a.name      = NULL;
+  a.val       = NULL;
+  a.def       = NULL;
+  return a;
+}
+
+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
+  struct arg arg;
+
+  if (!argv[0] || argv[0][0] != '-')
+    return 0;
+
+  arg = arg_init(argv);
+
+  if (def->short_name
+      && strlen(arg.argv[0]) == strlen(def->short_name) + 1
+      && !strcmp(arg.argv[0] + 1, def->short_name)) {
+
+    arg.name = arg.argv[0] + 1;
+    arg.val = def->has_val ? arg.argv[1] : NULL;
+    arg.argv_step = def->has_val ? 2 : 1;
+  } else if (def->long_name) {
+    const size_t name_len = strlen(def->long_name);
+
+    if (strlen(arg.argv[0]) >= name_len + 2
+        && arg.argv[0][1] == '-'
+        && !strncmp(arg.argv[0] + 2, def->long_name, name_len)
+        && (arg.argv[0][name_len + 2] == '='
+            || arg.argv[0][name_len + 2] == '\0')) {
+
+      arg.name = arg.argv[0] + 2;
+      arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
+      arg.argv_step = 1;
+    }
+  }
+
+  if (arg.name && !arg.val && def->has_val)
+    die("Error: option %s requires argument.\n", arg.name);
+
+  if (arg.name && arg.val && !def->has_val)
+    die("Error: option %s requires no argument.\n", arg.name);
+
+  if (arg.name
+      && (arg.val || !def->has_val)) {
+    arg.def = def;
+    *arg_ = arg;
+    return 1;
+  }
+
+  return 0;
+}
+
+
+const char *arg_next(struct arg *arg) {
+  if (arg->argv[0])
+    arg->argv += arg->argv_step;
+
+  return *arg->argv;
+}
+
+
+char **argv_dup(int argc, const char **argv) {
+  char **new_argv = malloc((argc + 1) * sizeof(*argv));
+
+  memcpy(new_argv, argv, argc * sizeof(*argv));
+  new_argv[argc] = NULL;
+  return new_argv;
+}
+
+
+void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
+  char option_text[40] = {0};
+
+  for (; *defs; defs++) {
+    const struct arg_def *def = *defs;
+    char *short_val = def->has_val ? " <arg>" : "";
+    char *long_val = def->has_val ? "=<arg>" : "";
+
+    if (def->short_name && def->long_name) {
+      char *comma = def->has_val ? "," : ",      ";
+
+      snprintf(option_text, 37, "-%s%s%s --%s%6s",
+               def->short_name, short_val, comma,
+               def->long_name, long_val);
+    } else if (def->short_name)
+      snprintf(option_text, 37, "-%s%s",
+               def->short_name, short_val);
+    else if (def->long_name)
+      snprintf(option_text, 37, "          --%s%s",
+               def->long_name, long_val);
+
+    fprintf(fp, "  %-37s\t%s\n", option_text, def->desc);
+
+    if (def->enums) {
+      const struct arg_enum_list *listptr;
+
+      fprintf(fp, "  %-37s\t  ", "");
+
+      for (listptr = def->enums; listptr->name; listptr++)
+        fprintf(fp, "%s%s", listptr->name,
+                listptr[1].name ? ", " : "\n");
+    }
+  }
+}
+
+
+unsigned int arg_parse_uint(const struct arg *arg) {
+  long int   rawval;
+  char      *endptr;
+
+  rawval = strtol(arg->val, &endptr, 10);
+
+  if (arg->val[0] != '\0' && endptr[0] == '\0') {
+    if (rawval >= 0 && rawval <= UINT_MAX)
+      return rawval;
+
+    die("Option %s: Value %ld out of range for unsigned int\n",
+        arg->name, rawval);
+  }
+
+  die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+  return 0;
+}
+
+
+int arg_parse_int(const struct arg *arg) {
+  long int   rawval;
+  char      *endptr;
+
+  rawval = strtol(arg->val, &endptr, 10);
+
+  if (arg->val[0] != '\0' && endptr[0] == '\0') {
+    if (rawval >= INT_MIN && rawval <= INT_MAX)
+      return rawval;
+
+    die("Option %s: Value %ld out of range for signed int\n",
+        arg->name, rawval);
+  }
+
+  die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+  return 0;
+}
+
+
+struct vpx_rational {
+  int num; /**< fraction numerator */
+  int den; /**< fraction denominator */
+};
+struct vpx_rational arg_parse_rational(const struct arg *arg) {
+  long int             rawval;
+  char                *endptr;
+  struct vpx_rational  rat;
+
+  /* parse numerator */
+  rawval = strtol(arg->val, &endptr, 10);
+
+  if (arg->val[0] != '\0' && endptr[0] == '/') {
+    if (rawval >= INT_MIN && rawval <= INT_MAX)
+      rat.num = rawval;
+    else die("Option %s: Value %ld out of range for signed int\n",
+               arg->name, rawval);
+  } else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
+
+  /* parse denominator */
+  rawval = strtol(endptr + 1, &endptr, 10);
+
+  if (arg->val[0] != '\0' && endptr[0] == '\0') {
+    if (rawval >= INT_MIN && rawval <= INT_MAX)
+      rat.den = rawval;
+    else die("Option %s: Value %ld out of range for signed int\n",
+               arg->name, rawval);
+  } else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
+
+  return rat;
+}
+
+
+int arg_parse_enum(const struct arg *arg) {
+  const struct arg_enum_list *listptr;
+  long int                    rawval;
+  char                       *endptr;
+
+  /* First see if the value can be parsed as a raw value */
+  rawval = strtol(arg->val, &endptr, 10);
+  if (arg->val[0] != '\0' && endptr[0] == '\0') {
+    /* Got a raw value, make sure it's valid */
+    for (listptr = arg->def->enums; listptr->name; listptr++)
+      if (listptr->val == rawval)
+        return rawval;
+  }
+
+  /* Next see if it can be parsed as a string */
+  for (listptr = arg->def->enums; listptr->name; listptr++)
+    if (!strcmp(arg->val, listptr->name))
+      return listptr->val;
+
+  die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
+  return 0;
+}
+
+
+int arg_parse_enum_or_int(const struct arg *arg) {
+  if (arg->def->enums)
+    return arg_parse_enum(arg);
+  return arg_parse_int(arg);
+}
diff --git a/src/third_party/libvpx/args.h b/src/third_party/libvpx/args.h
new file mode 100644
index 0000000..1f37151
--- /dev/null
+++ b/src/third_party/libvpx/args.h
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2010 The WebM 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 ARGS_H_
+#define ARGS_H_
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct arg {
+  char                 **argv;
+  const char            *name;
+  const char            *val;
+  unsigned int           argv_step;
+  const struct arg_def  *def;
+};
+
+struct arg_enum_list {
+  const char *name;
+  int         val;
+};
+#define ARG_ENUM_LIST_END {0}
+
+typedef struct arg_def {
+  const char *short_name;
+  const char *long_name;
+  int         has_val;
+  const char *desc;
+  const struct arg_enum_list *enums;
+} arg_def_t;
+#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
+#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
+#define ARG_DEF_LIST_END {0}
+
+struct arg arg_init(char **argv);
+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
+const char *arg_next(struct arg *arg);
+void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
+char **argv_dup(int argc, const char **argv);
+
+unsigned int arg_parse_uint(const struct arg *arg);
+int arg_parse_int(const struct arg *arg);
+struct vpx_rational arg_parse_rational(const struct arg *arg);
+int arg_parse_enum(const struct arg *arg);
+int arg_parse_enum_or_int(const struct arg *arg);
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // ARGS_H_
diff --git a/src/third_party/libvpx/build/make/Android.mk b/src/third_party/libvpx/build/make/Android.mk
new file mode 100644
index 0000000..df01dec
--- /dev/null
+++ b/src/third_party/libvpx/build/make/Android.mk
@@ -0,0 +1,205 @@
+##
+##  Copyright (c) 2012 The WebM 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.
+##
+
+#
+# This file is to be used for compiling libvpx for Android using the NDK.
+# In an Android project place a libvpx checkout in the jni directory.
+# Run the configure script from the jni directory.  Base libvpx
+# encoder/decoder configuration will look similar to:
+# ./libvpx/configure --target=armv7-android-gcc --disable-examples \
+#                    --sdk-path=/opt/android-ndk-r6b/
+#
+# When targeting Android, realtime-only is enabled by default.  This can
+# be overridden by adding the command line flag:
+#  --disable-realtime-only
+#
+# This will create .mk files that contain variables that contain the
+# source files to compile.
+#
+# Place an Android.mk file in the jni directory that references the
+# Android.mk file in the libvpx directory:
+# LOCAL_PATH := $(call my-dir)
+# include $(CLEAR_VARS)
+# include jni/libvpx/build/make/Android.mk
+#
+# There are currently two TARGET_ARCH_ABI targets for ARM.
+# armeabi and armeabi-v7a.  armeabi-v7a is selected by creating an
+# Application.mk in the jni directory that contains:
+# APP_ABI := armeabi-v7a
+#
+# By default libvpx will detect at runtime the existance of NEON extension.
+# For this we import the 'cpufeatures' module from the NDK sources.
+# libvpx can also be configured without this runtime detection method.
+# Configuring with --disable-runtime-cpu-detect will assume presence of NEON.
+# Configuring with --disable-runtime-cpu-detect --disable-neon \
+#     --disable-neon-asm
+# will remove any NEON dependency.
+
+# To change to building armeabi, run ./libvpx/configure again, but with
+# --target=armv6-android-gcc and modify the Application.mk file to
+# set APP_ABI := armeabi
+#
+# Running ndk-build will build libvpx and include it in your project.
+#
+
+CONFIG_DIR := $(LOCAL_PATH)/
+LIBVPX_PATH := $(LOCAL_PATH)/libvpx
+ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas
+ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
+
+# Use the makefiles generated by upstream configure to determine which files to
+# build. Also set any architecture-specific flags.
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+  include $(CONFIG_DIR)libs-armv7-android-gcc.mk
+  LOCAL_ARM_MODE := arm
+else ifeq  ($(TARGET_ARCH_ABI),armeabi)
+  include $(CONFIG_DIR)libs-armv6-android-gcc.mk
+  LOCAL_ARM_MODE := arm
+else ifeq  ($(TARGET_ARCH_ABI),arm64-v8a)
+  include $(CONFIG_DIR)libs-armv8-android-gcc.mk
+  LOCAL_ARM_MODE := arm
+else ifeq ($(TARGET_ARCH_ABI),x86)
+  include $(CONFIG_DIR)libs-x86-android-gcc.mk
+else ifeq ($(TARGET_ARCH_ABI),x86_64)
+  include $(CONFIG_DIR)libs-x86_64-android-gcc.mk
+else ifeq ($(TARGET_ARCH_ABI),mips)
+  include $(CONFIG_DIR)libs-mips-android-gcc.mk
+else
+  $(error Not a supported TARGET_ARCH_ABI: $(TARGET_ARCH_ABI))
+endif
+
+# Rule that is normally in Makefile created by libvpx
+# configure.  Used to filter out source files based on configuration.
+enabled=$(filter-out $($(1)-no),$($(1)-yes))
+
+# Override the relative path that is defined by the libvpx
+# configure process
+SRC_PATH_BARE := $(LIBVPX_PATH)
+
+# Include the list of files to be built
+include $(LIBVPX_PATH)/libs.mk
+
+# Optimise the code. May want to revisit this setting in the future.
+LOCAL_CFLAGS := -O3
+
+# For x86, include the source code in the search path so it will find files
+# like x86inc.asm and x86_abi_support.asm
+LOCAL_ASMFLAGS := -I$(LIBVPX_PATH)
+
+.PRECIOUS: %.asm.s
+$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm
+	@mkdir -p $(dir $@)
+	@$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
+
+# For building *_rtcd.h, which have rules in libs.mk
+TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
+target := libs
+
+LOCAL_SRC_FILES += vpx_config.c
+
+# Remove duplicate entries
+CODEC_SRCS_UNIQUE = $(sort $(CODEC_SRCS))
+
+# Pull out C files.  vpx_config.c is in the immediate directory and
+# so it does not need libvpx/ prefixed like the rest of the source files.
+# The neon files with intrinsics need to have .neon appended so the proper
+# flags are applied.
+CODEC_SRCS_C = $(filter %.c, $(CODEC_SRCS_UNIQUE))
+LOCAL_NEON_SRCS_C = $(filter %_neon.c, $(CODEC_SRCS_C))
+LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c %_neon.c, $(CODEC_SRCS_C))
+
+LOCAL_SRC_FILES += $(foreach file, $(LOCAL_CODEC_SRCS_C), libvpx/$(file))
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+  LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file).neon)
+else # If there are neon sources then we are building for arm64 and do not need to specify .neon
+  LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file))
+endif
+
+# Pull out assembly files, splitting NEON from the rest.  This is
+# done to specify that the NEON assembly files use NEON assembler flags.
+# x86 assembly matches %.asm, arm matches %.asm.s
+
+# x86:
+
+CODEC_SRCS_ASM_X86 = $(filter %.asm, $(CODEC_SRCS_UNIQUE))
+LOCAL_SRC_FILES += $(foreach file, $(CODEC_SRCS_ASM_X86), libvpx/$(file))
+
+# arm:
+CODEC_SRCS_ASM_ARM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE))
+CODEC_SRCS_ASM_ARM = $(foreach v, \
+                     $(CODEC_SRCS_ASM_ARM_ALL), \
+                     $(if $(findstring neon,$(v)),,$(v)))
+CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \
+                         $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
+                         $(CODEC_SRCS_ASM_ARM))
+LOCAL_SRC_FILES += $(CODEC_SRCS_ASM_ADS2GAS)
+
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+  CODEC_SRCS_ASM_NEON = $(foreach v, \
+                        $(CODEC_SRCS_ASM_ARM_ALL),\
+                        $(if $(findstring neon,$(v)),$(v),))
+  CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.s, \
+                                $(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
+                                $(CODEC_SRCS_ASM_NEON))
+  LOCAL_SRC_FILES += $(patsubst %.s, \
+                     %.s.neon, \
+                     $(CODEC_SRCS_ASM_NEON_ADS2GAS))
+endif
+
+LOCAL_CFLAGS += \
+    -DHAVE_CONFIG_H=vpx_config.h \
+    -I$(LIBVPX_PATH) \
+    -I$(ASM_CNV_PATH)
+
+LOCAL_MODULE := libvpx
+
+ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
+  LOCAL_STATIC_LIBRARIES := cpufeatures
+endif
+
+# Add a dependency to force generation of the RTCD files.
+define rtcd_dep_template
+rtcd_dep_template_SRCS := $(addprefix $(LOCAL_PATH)/, $(LOCAL_SRC_FILES))
+rtcd_dep_template_SRCS := $$(rtcd_dep_template_SRCS:.neon=)
+ifeq ($(CONFIG_VP8), yes)
+$$(rtcd_dep_template_SRCS): vp8_rtcd.h
+endif
+ifeq ($(CONFIG_VP9), yes)
+$$(rtcd_dep_template_SRCS): vp9_rtcd.h
+endif
+ifeq ($(CONFIG_VP10), yes)
+$$(rtcd_dep_template_SRCS): vp10_rtcd.h
+endif
+$$(rtcd_dep_template_SRCS): vpx_scale_rtcd.h
+$$(rtcd_dep_template_SRCS): vpx_dsp_rtcd.h
+
+ifneq ($(findstring $(TARGET_ARCH_ABI),x86 x86_64),)
+$$(rtcd_dep_template_SRCS): vpx_config.asm
+endif
+endef
+
+$(eval $(call rtcd_dep_template))
+
+.PHONY: clean
+clean:
+	@echo "Clean: ads2gas files [$(TARGET_ARCH_ABI)]"
+	@$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
+	@$(RM) -r $(ASM_CNV_PATH)
+	@$(RM) $(CLEAN-OBJS)
+
+ifeq ($(ENABLE_SHARED),1)
+  include $(BUILD_SHARED_LIBRARY)
+else
+  include $(BUILD_STATIC_LIBRARY)
+endif
+
+ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
+$(call import-module,cpufeatures)
+endif
diff --git a/src/third_party/libvpx/build/make/Makefile b/src/third_party/libvpx/build/make/Makefile
new file mode 100644
index 0000000..3e8c0249
--- /dev/null
+++ b/src/third_party/libvpx/build/make/Makefile
@@ -0,0 +1,451 @@
+##
+##  Copyright (c) 2010 The WebM 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 config.mk
+quiet?=true
+ifeq ($(target),)
+# If a target wasn't specified, invoke for all enabled targets.
+.DEFAULT:
+	@for t in $(ALL_TARGETS); do \
+	     $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
+        done
+all: .DEFAULT
+clean:: .DEFAULT
+exampletest: .DEFAULT
+install:: .DEFAULT
+test:: .DEFAULT
+test-no-data-check:: .DEFAULT
+testdata:: .DEFAULT
+utiltest: .DEFAULT
+exampletest-no-data-check utiltest-no-data-check: .DEFAULT
+
+
+# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
+# installed on cygwin, so we need to autodetect here.
+md5sum := $(firstword $(wildcard \
+          $(foreach e,md5sum openssl,\
+          $(foreach p,$(subst :, ,$(PATH)),$(p)/$(e)*))\
+          ))
+md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum))
+
+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
+dist:
+	@for t in $(ALL_TARGETS); do \
+	     $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
+        done
+        # Run configure for the user with the current toolchain.
+	@if [ -d "$(DIST_DIR)/src" ]; then \
+            mkdir -p "$(DIST_DIR)/build"; \
+            cd "$(DIST_DIR)/build"; \
+            echo "Rerunning configure $(CONFIGURE_ARGS)"; \
+            ../src/configure $(CONFIGURE_ARGS); \
+            $(if $(filter vs%,$(TGT_CC)),make NO_LAUNCH_DEVENV=1;) \
+        fi
+	@if [ -d "$(DIST_DIR)" ]; then \
+            echo "    [MD5SUM] $(DIST_DIR)"; \
+	    cd $(DIST_DIR) && \
+	    $(md5sum) `find . -name md5sums.txt -prune -o -type f -print` \
+                | sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2  \1/' \
+                > md5sums.txt;\
+        fi
+endif
+
+# Since we invoke make recursively for multiple targets we need to include the
+# .mk file for the correct target, but only when $(target) is non-empty.
+ifneq ($(target),)
+include $(target)-$(TOOLCHAIN).mk
+endif
+BUILD_ROOT?=.
+VPATH=$(SRC_PATH_BARE)
+CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
+CXXFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
+ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT)/ -I$(SRC_PATH)/
+DIST_DIR?=dist
+HOSTCC?=gcc
+TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
+TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN)))
+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
+quiet:=$(if $(or $(verbose), $(V)),, yes)
+qexec=$(if $(quiet),@)
+
+# Cancel built-in implicit rules
+%: %.o
+%.asm:
+%.a:
+%: %.cc
+
+#
+# Common rules"
+#
+.PHONY: all
+all:
+
+.PHONY: clean
+clean::
+	rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
+	rm -f $(CLEAN-OBJS)
+
+.PHONY: clean
+distclean: clean
+	if [ -z "$(target)" ]; then \
+      rm -f Makefile; \
+      rm -f config.log config.mk; \
+      rm -f vpx_config.[hc] vpx_config.asm; \
+    else \
+      rm -f $(target)-$(TOOLCHAIN).mk; \
+    fi
+
+.PHONY: dist
+dist:
+.PHONY: exampletest
+exampletest:
+.PHONY: install
+install::
+.PHONY: test
+test::
+.PHONY: testdata
+testdata::
+.PHONY: utiltest
+utiltest:
+.PHONY: test-no-data-check exampletest-no-data-check utiltest-no-data-check
+test-no-data-check::
+exampletest-no-data-check utiltest-no-data-check:
+
+# Force to realign stack always on OS/2
+ifeq ($(TOOLCHAIN), x86-os2-gcc)
+CFLAGS += -mstackrealign
+endif
+
+$(BUILD_PFX)%_mmx.c.d: CFLAGS += -mmmx
+$(BUILD_PFX)%_mmx.c.o: CFLAGS += -mmmx
+$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2
+$(BUILD_PFX)%_sse2.c.o: CFLAGS += -msse2
+$(BUILD_PFX)%_sse3.c.d: CFLAGS += -msse3
+$(BUILD_PFX)%_sse3.c.o: CFLAGS += -msse3
+$(BUILD_PFX)%_ssse3.c.d: CFLAGS += -mssse3
+$(BUILD_PFX)%_ssse3.c.o: CFLAGS += -mssse3
+$(BUILD_PFX)%_sse4.c.d: CFLAGS += -msse4.1
+$(BUILD_PFX)%_sse4.c.o: CFLAGS += -msse4.1
+$(BUILD_PFX)%_avx.c.d: CFLAGS += -mavx
+$(BUILD_PFX)%_avx.c.o: CFLAGS += -mavx
+$(BUILD_PFX)%_avx2.c.d: CFLAGS += -mavx2
+$(BUILD_PFX)%_avx2.c.o: CFLAGS += -mavx2
+
+$(BUILD_PFX)%.c.d: %.c
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.c.o: %.c
+	$(if $(quiet),@echo "    [CC] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
+
+$(BUILD_PFX)%.cc.d: %.cc
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.cc.o: %.cc
+	$(if $(quiet),@echo "    [CXX] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+$(BUILD_PFX)%.cpp.d: %.cpp
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
+
+$(BUILD_PFX)%.cpp.o: %.cpp
+	$(if $(quiet),@echo "    [CXX] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
+
+$(BUILD_PFX)%.asm.d: %.asm
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
+            --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
+
+$(BUILD_PFX)%.asm.o: %.asm
+	$(if $(quiet),@echo "    [AS] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(AS) $(ASFLAGS) -o $@ $<
+
+$(BUILD_PFX)%.s.d: %.s
+	$(if $(quiet),@echo "    [DEP] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
+            --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
+
+$(BUILD_PFX)%.s.o: %.s
+	$(if $(quiet),@echo "    [AS] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(AS) $(ASFLAGS) -o $@ $<
+
+.PRECIOUS: %.c.S
+%.c.S: CFLAGS += -DINLINE_ASM
+$(BUILD_PFX)%.c.S: %.c
+	$(if $(quiet),@echo "    [GEN] $@")
+	$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
+	$(qexec)$(CC) -S $(CFLAGS) -o $@ $<
+
+.PRECIOUS: %.asm.s
+$(BUILD_PFX)%.asm.s: %.asm
+	$(if $(quiet),@echo "    [ASM CONVERSION] $@")
+	$(qexec)mkdir -p $(dir $@)
+	$(qexec)$(ASM_CONVERSION) <$< >$@
+
+# If we're in debug mode, pretend we don't have GNU strip, to fall back to
+# the copy implementation
+HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
+ifeq ($(HAVE_GNU_STRIP),yes)
+# Older binutils strip global symbols not needed for relocation processing
+# when given --strip-unneeded. Using nm and awk to identify globals and
+# keep them caused command line length issues under mingw and segfaults in
+# test_libvpx were observed under OS/2: simply use --strip-debug.
+%.a: %_g.a
+	$(if $(quiet),@echo "    [STRIP] $@ < $<")
+	$(qexec)$(STRIP) --strip-debug \
+          -o $@ $<
+else
+%.a: %_g.a
+	$(if $(quiet),@echo "    [CP] $@ < $<")
+	$(qexec)cp $< $@
+endif
+
+#
+# Utility functions
+#
+pairmap=$(if $(strip $(2)),\
+    $(call $(1),$(word 1,$(2)),$(word 2,$(2)))\
+    $(call pairmap,$(1),$(wordlist 3,$(words $(2)),$(2)))\
+)
+
+enabled=$(filter-out $($(1)-no),$($(1)-yes))
+cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
+
+find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
+find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
+obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o
+objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
+
+install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
+
+not=$(subst yes,no,$(1))
+
+ifeq ($(CONFIG_MSVS),yes)
+lib_file_name=$(1).lib
+else
+lib_file_name=lib$(1).a
+endif
+#
+# Rule Templates
+#
+define linker_template
+$(1): $(filter-out -%,$(2))
+$(1):
+	$(if $(quiet),@echo    "    [LD] $$@")
+	$(qexec)$$(LD) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
+endef
+define linkerxx_template
+$(1): $(filter-out -%,$(2))
+$(1):
+	$(if $(quiet),@echo    "    [LD] $$@")
+	$(qexec)$$(CXX) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
+endef
+# make-3.80 has a bug with expanding large input strings to the eval function,
+# which was triggered in some cases by the following component of
+# linker_template:
+#   $(1): $$(call find_file, $(patsubst -l%,lib%.a,$(filter -l%,$(2))),\
+#                           $$(patsubst -L%,%,$$(filter -L%,$$(LDFLAGS) $(2))))
+# This may be useful to revisit in the future (it tries to locate libraries
+# in a search path and add them as prerequisites
+
+define install_map_template
+$(DIST_DIR)/$(1): $(2)
+	$(if $(quiet),@echo "    [INSTALL] $$@")
+	$(qexec)mkdir -p $$(dir $$@)
+	$(qexec)cp -p $$< $$@
+endef
+
+define archive_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+$(1):
+	$(if $(quiet),@echo "    [AR] $$@")
+	$(qexec)$$(AR) $$(ARFLAGS) $$@ $$^
+endef
+
+define so_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+#
+# This needs further abstraction for dealing with non-GNU linkers.
+$(1):
+	$(if $(quiet),@echo "    [LD] $$@")
+	$(qexec)$$(LD) -shared $$(LDFLAGS) \
+            -Wl,--no-undefined -Wl,-soname,$$(SONAME) \
+            -Wl,--version-script,$$(EXPORTS_FILE) -o $$@ \
+            $$(filter %.o,$$^) $$(extralibs)
+endef
+
+define dl_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+$(1):
+	$(if $(quiet),@echo "    [LD] $$@")
+	$(qexec)$$(LD) -dynamiclib $$(LDFLAGS) \
+	    -exported_symbols_list $$(EXPORTS_FILE) \
+        -Wl,-headerpad_max_install_names,-compatibility_version,1.0,-current_version,$$(VERSION_MAJOR) \
+        -o $$@ \
+        $$(filter %.o,$$^) $$(extralibs)
+endef
+
+define dll_template
+# Not using a pattern rule here because we don't want to generate empty
+# archives when they are listed as a dependency in files not responsible
+# for creating them.
+$(1):
+	$(if $(quiet),@echo "    [LD] $$@")
+	$(qexec)$$(LD) -Zdll $$(LDFLAGS) \
+        -o $$@ \
+        $$(filter %.o,$$^) $$(extralibs) $$(EXPORTS_FILE)
+endef
+
+
+#
+# Get current configuration
+#
+ifneq ($(target),)
+include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
+endif
+
+skip_deps := $(filter %clean,$(MAKECMDGOALS))
+skip_deps += $(findstring testdata,$(MAKECMDGOALS))
+ifeq ($(strip $(skip_deps)),)
+  ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes)
+    # Older versions of make don't like -include directives with no arguments
+    ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
+      -include $(filter %.d,$(OBJS-yes:.o=.d))
+    endif
+  endif
+endif
+
+#
+# Configuration dependent rules
+#
+$(call pairmap,install_map_templates,$(INSTALL_MAPS))
+
+DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS)
+.docs: $(DOCS)
+	@touch $@
+
+INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-DOCS+=$(call cond_enabled,CONFIG_INSTALL_DOCS,DIST-DOCS)
+endif
+.install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS))
+	@touch $@
+
+clean::
+	rm -f .docs .install-docs $(DOCS)
+
+BINS=$(call enabled,BINS)
+.bins: $(BINS)
+	@touch $@
+
+INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-BINS+=$(call cond_enabled,CONFIG_INSTALL_BINS,DIST-BINS)
+endif
+.install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS))
+	@touch $@
+
+clean::
+	rm -f .bins .install-bins $(BINS)
+
+LIBS=$(call enabled,LIBS)
+.libs: $(LIBS)
+	@touch $@
+$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
+$(foreach lib,$(filter %so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
+$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dylib,$(LIBS)),$(eval $(call dl_template,$(lib))))
+$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dll,$(LIBS)),$(eval $(call dll_template,$(lib))))
+
+INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-LIBS+=$(call cond_enabled,CONFIG_INSTALL_LIBS,DIST-LIBS)
+endif
+.install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS))
+	@touch $@
+
+clean::
+	rm -f .libs .install-libs $(LIBS)
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+PROJECTS=$(call enabled,PROJECTS)
+.projects: $(PROJECTS)
+	@touch $@
+
+INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-PROJECTS+=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,DIST-PROJECTS)
+endif
+.install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS))
+	@touch $@
+
+clean::
+	rm -f .projects .install-projects $(PROJECTS)
+endif
+
+# If there are any source files to be distributed, then include the build
+# system too.
+ifneq ($(call enabled,DIST-SRCS),)
+    DIST-SRCS-yes            += configure
+    DIST-SRCS-yes            += build/make/configure.sh
+    DIST-SRCS-yes            += build/make/gen_asm_deps.sh
+    DIST-SRCS-yes            += build/make/Makefile
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_def.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_proj.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_sln.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/gen_msvs_vcxproj.sh
+    DIST-SRCS-$(CONFIG_MSVS)  += build/make/msvs_common.sh
+    DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
+    DIST-SRCS-$(ARCH_ARM)    += build/make/ads2gas.pl
+    DIST-SRCS-$(ARCH_ARM)    += build/make/ads2gas_apple.pl
+    DIST-SRCS-$(ARCH_ARM)    += build/make/ads2armasm_ms.pl
+    DIST-SRCS-$(ARCH_ARM)    += build/make/thumb.pm
+    DIST-SRCS-yes            += $(target:-$(TOOLCHAIN)=).mk
+endif
+INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
+ifeq ($(MAKECMDGOALS),dist)
+INSTALL-SRCS += $(call cond_enabled,CONFIG_INSTALL_SRCS,DIST-SRCS)
+endif
+.install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS))
+	@touch $@
+
+clean::
+	rm -f .install-srcs
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+    BUILD_TARGETS += .projects
+    INSTALL_TARGETS += .install-projects
+endif
+BUILD_TARGETS += .docs .libs .bins
+INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins
+all: $(BUILD_TARGETS)
+install:: $(INSTALL_TARGETS)
+dist: $(INSTALL_TARGETS)
+test::
diff --git a/src/third_party/libvpx/build/make/ads2armasm_ms.pl b/src/third_party/libvpx/build/make/ads2armasm_ms.pl
new file mode 100755
index 0000000..2a2c470
--- /dev/null
+++ b/src/third_party/libvpx/build/make/ads2armasm_ms.pl
@@ -0,0 +1,39 @@
+#!/usr/bin/env perl
+##
+##  Copyright (c) 2013 The WebM 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.
+##
+
+use FindBin;
+use lib $FindBin::Bin;
+use thumb;
+
+print "; This file was created from a .asm file\n";
+print ";  using the ads2armasm_ms.pl script.\n";
+
+while (<STDIN>)
+{
+    undef $comment;
+    undef $line;
+
+    s/REQUIRE8//;
+    s/PRESERVE8//;
+    s/^\s*ARM\s*$//;
+    s/AREA\s+\|\|(.*)\|\|/AREA |$1|/;
+    s/qsubaddx/qsax/i;
+    s/qaddsubx/qasx/i;
+
+    thumb::FixThumbInstructions($_, 1);
+
+    s/ldrneb/ldrbne/i;
+    s/ldrneh/ldrhne/i;
+    s/^(\s*)ENDP.*/$&\n$1ALIGN 4/;
+
+    print;
+}
+
diff --git a/src/third_party/libvpx/build/make/ads2gas.pl b/src/third_party/libvpx/build/make/ads2gas.pl
new file mode 100755
index 0000000..7272424
--- /dev/null
+++ b/src/third_party/libvpx/build/make/ads2gas.pl
@@ -0,0 +1,236 @@
+#!/usr/bin/env perl
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+# ads2gas.pl
+# Author: Eric Fung (efung (at) acm.org)
+#
+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
+#
+# Usage: cat inputfile | perl ads2gas.pl > outputfile
+#
+
+use FindBin;
+use lib $FindBin::Bin;
+use thumb;
+
+my $thumb = 0;
+
+foreach my $arg (@ARGV) {
+    $thumb = 1 if ($arg eq "-thumb");
+}
+
+print "@ This file was created from a .asm file\n";
+print "@  using the ads2gas.pl script.\n";
+print "\t.equ DO1STROUNDING, 0\n";
+if ($thumb) {
+    print "\t.syntax unified\n";
+    print "\t.thumb\n";
+}
+
+# Stack of procedure names.
+@proc_stack = ();
+
+while (<STDIN>)
+{
+    undef $comment;
+    undef $line;
+    $comment_char = ";";
+    $comment_sub = "@";
+
+    # Handle comments.
+    if (/$comment_char/)
+    {
+      $comment = "";
+      ($line, $comment) = /(.*?)$comment_char(.*)/;
+      $_ = $line;
+    }
+
+    # Load and store alignment
+    s/@/,:/g;
+
+    # Hexadecimal constants prefaced by 0x
+    s/#&/#0x/g;
+
+    # Convert :OR: to |
+    s/:OR:/ | /g;
+
+    # Convert :AND: to &
+    s/:AND:/ & /g;
+
+    # Convert :NOT: to ~
+    s/:NOT:/ ~ /g;
+
+    # Convert :SHL: to <<
+    s/:SHL:/ << /g;
+
+    # Convert :SHR: to >>
+    s/:SHR:/ >> /g;
+
+    # Convert ELSE to .else
+    s/\bELSE\b/.else/g;
+
+    # Convert ENDIF to .endif
+    s/\bENDIF\b/.endif/g;
+
+    # Convert ELSEIF to .elseif
+    s/\bELSEIF\b/.elseif/g;
+
+    # Convert LTORG to .ltorg
+    s/\bLTORG\b/.ltorg/g;
+
+    # Convert endfunc to nothing.
+    s/\bendfunc\b//ig;
+
+    # Convert FUNCTION to nothing.
+    s/\bFUNCTION\b//g;
+    s/\bfunction\b//g;
+
+    s/\bENTRY\b//g;
+    s/\bMSARMASM\b/0/g;
+    s/^\s+end\s+$//g;
+
+    # Convert IF :DEF:to .if
+    # gcc doesn't have the ability to do a conditional
+    # if defined variable that is set by IF :DEF: on
+    # armasm, so convert it to a normal .if and then
+    # make sure to define a value elesewhere
+    if (s/\bIF :DEF:\b/.if /g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert IF to .if
+    if (s/\bIF\b/.if/g)
+    {
+        s/=+/==/g;
+    }
+
+    # Convert INCLUDE to .INCLUDE "file"
+    s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
+
+    # Code directive (ARM vs Thumb)
+    s/CODE([0-9][0-9])/.code $1/;
+
+    # No AREA required
+    # But ALIGNs in AREA must be obeyed
+    s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+    # If no ALIGN, strip the AREA and align to 4 bytes
+    s/^\s*AREA.*$/.text\n.p2align 2/;
+
+    # DCD to .word
+    # This one is for incoming symbols
+    s/DCD\s+\|(\w*)\|/.long $1/;
+
+    # DCW to .short
+    s/DCW\s+\|(\w*)\|/.short $1/;
+    s/DCW(.*)/.short $1/;
+
+    # Constants defined in scope
+    s/DCD(.*)/.long $1/;
+    s/DCB(.*)/.byte $1/;
+
+    # RN to .req
+    if (s/RN\s+([Rr]\d+|lr)/.req $1/)
+    {
+        print;
+        print "$comment_sub$comment\n" if defined $comment;
+        next;
+    }
+
+    # Make function visible to linker, and make additional symbol with
+    # prepended underscore
+    s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
+    s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
+
+    s/EXPORT\s+([\$\w]*)/.global $1/;
+    s/export\s+([\$\w]*)/.global $1/;
+
+    # No vertical bars required; make additional symbol with prepended
+    # underscore
+    s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
+
+    # Labels need trailing colon
+#   s/^(\w+)/$1:/ if !/EQU/;
+    # put the colon at the end of the line in the macro
+    s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
+
+    # ALIGN directive
+    s/\bALIGN\b/.balign/g;
+
+    if ($thumb) {
+        # ARM code - we force everything to thumb with the declaration in the header
+        s/\sARM//g;
+    } else {
+        # ARM code
+        s/\sARM/.arm/g;
+    }
+
+    # push/pop
+    s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g;
+    s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g;
+
+    # NEON code
+    s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g;
+    s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g;
+
+    if ($thumb) {
+        thumb::FixThumbInstructions($_, 0);
+    }
+
+    # eabi_attributes numerical equivalents can be found in the
+    # "ARM IHI 0045C" document.
+
+    # REQUIRE8 Stack is required to be 8-byte aligned
+    s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
+
+    # PRESERVE8 Stack 8-byte align is preserved
+    s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
+
+    # Use PROC and ENDP to give the symbols a .size directive.
+    # This makes them show up properly in debugging tools like gdb and valgrind.
+    if (/\bPROC\b/)
+    {
+        my $proc;
+        /^_([\.0-9A-Z_a-z]\w+)\b/;
+        $proc = $1;
+        push(@proc_stack, $proc) if ($proc);
+        s/\bPROC\b/@ $&/;
+    }
+    if (/\bENDP\b/)
+    {
+        my $proc;
+        s/\bENDP\b/@ $&/;
+        $proc = pop(@proc_stack);
+        $_ = "\t.size $proc, .-$proc".$_ if ($proc);
+    }
+
+    # EQU directive
+    s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/;
+
+    # Begin macro definition
+    if (/\bMACRO\b/) {
+        $_ = <STDIN>;
+        s/^/.macro/;
+        s/\$//g;                # remove formal param reference
+        s/;/@/g;                # change comment characters
+    }
+
+    # For macros, use \ to reference formal params
+    s/\$/\\/g;                  # End macro definition
+    s/\bMEND\b/.endm/;              # No need to tell it where to stop assembling
+    next if /^\s*END\s*$/;
+    print;
+    print "$comment_sub$comment\n" if defined $comment;
+}
+
+# Mark that this object doesn't need an executable stack.
+printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");
diff --git a/src/third_party/libvpx/build/make/ads2gas_apple.pl b/src/third_party/libvpx/build/make/ads2gas_apple.pl
new file mode 100755
index 0000000..a82f3eb
--- /dev/null
+++ b/src/third_party/libvpx/build/make/ads2gas_apple.pl
@@ -0,0 +1,235 @@
+#!/usr/bin/env perl
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+# ads2gas_apple.pl
+# Author: Eric Fung (efung (at) acm.org)
+#
+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
+#
+# Usage: cat inputfile | perl ads2gas_apple.pl > outputfile
+#
+
+my $chromium = 0;
+
+foreach my $arg (@ARGV) {
+    $chromium = 1 if ($arg eq "-chromium");
+}
+
+print "@ This file was created from a .asm file\n";
+print "@  using the ads2gas_apple.pl script.\n\n";
+print "\t.set WIDE_REFERENCE, 0\n";
+print "\t.set ARCHITECTURE, 5\n";
+print "\t.set DO1STROUNDING, 0\n";
+
+my %register_aliases;
+my %macro_aliases;
+
+my @mapping_list = ("\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", "\$8", "\$9");
+
+my @incoming_array;
+
+my @imported_functions;
+
+# Perl trim function to remove whitespace from the start and end of the string
+sub trim($)
+{
+    my $string = shift;
+    $string =~ s/^\s+//;
+    $string =~ s/\s+$//;
+    return $string;
+}
+
+while (<STDIN>)
+{
+    # Load and store alignment
+    s/@/,:/g;
+
+    # Comment character
+    s/;/ @/g;
+
+    # Hexadecimal constants prefaced by 0x
+    s/#&/#0x/g;
+
+    # Convert :OR: to |
+    s/:OR:/ | /g;
+
+    # Convert :AND: to &
+    s/:AND:/ & /g;
+
+    # Convert :NOT: to ~
+    s/:NOT:/ ~ /g;
+
+    # Convert :SHL: to <<
+    s/:SHL:/ << /g;
+
+    # Convert :SHR: to >>
+    s/:SHR:/ >> /g;
+
+    # Convert ELSE to .else
+    s/\bELSE\b/.else/g;
+
+    # Convert ENDIF to .endif
+    s/\bENDIF\b/.endif/g;
+
+    # Convert ELSEIF to .elseif
+    s/\bELSEIF\b/.elseif/g;
+
+    # Convert LTORG to .ltorg
+    s/\bLTORG\b/.ltorg/g;
+
+    # Convert IF :DEF:to .if
+    # gcc doesn't have the ability to do a conditional
+    # if defined variable that is set by IF :DEF: on
+    # armasm, so convert it to a normal .if and then
+    # make sure to define a value elesewhere
+    if (s/\bIF :DEF:\b/.if /g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert IF to .if
+    if (s/\bIF\b/.if/g)
+    {
+        s/=/==/g;
+    }
+
+    # Convert INCLUDE to .INCLUDE "file"
+    s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
+
+    # Code directive (ARM vs Thumb)
+    s/CODE([0-9][0-9])/.code $1/;
+
+    # No AREA required
+    # But ALIGNs in AREA must be obeyed
+    s/^\s*AREA.*ALIGN=([0-9])$/.text\n.p2align $1/;
+    # If no ALIGN, strip the AREA and align to 4 bytes
+    s/^\s*AREA.*$/.text\n.p2align 2/;
+
+    # DCD to .word
+    # This one is for incoming symbols
+    s/DCD\s+\|(\w*)\|/.long $1/;
+
+    # DCW to .short
+    s/DCW\s+\|(\w*)\|/.short $1/;
+    s/DCW(.*)/.short $1/;
+
+    # Constants defined in scope
+    s/DCD(.*)/.long $1/;
+    s/DCB(.*)/.byte $1/;
+
+    # Build a hash of all the register - alias pairs.
+    if (s/(.*)RN(.*)/$1 .req $2/g)
+    {
+        $register_aliases{trim($1)} = trim($2);
+        next;
+    }
+
+    while (($key, $value) = each(%register_aliases))
+    {
+        s/\b$key\b/$value/g;
+    }
+
+    # Make function visible to linker, and make additional symbol with
+    # prepended underscore
+    s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/;
+
+    # Prepend imported functions with _
+    if (s/IMPORT\s+\|([\$\w]*)\|/.globl $1/)
+    {
+        $function = trim($1);
+        push(@imported_functions, $function);
+    }
+
+    foreach $function (@imported_functions)
+    {
+        s/$function/_$function/;
+    }
+
+    # No vertical bars required; make additional symbol with prepended
+    # underscore
+    s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
+
+    # Labels need trailing colon
+#   s/^(\w+)/$1:/ if !/EQU/;
+    # put the colon at the end of the line in the macro
+    s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
+
+    # ALIGN directive
+    s/\bALIGN\b/.balign/g;
+
+    # Strip ARM
+    s/\sARM/@ ARM/g;
+
+    # Strip REQUIRE8
+    #s/\sREQUIRE8/@ REQUIRE8/g;
+    s/\sREQUIRE8/@ /g;
+
+    # Strip PRESERVE8
+    s/\sPRESERVE8/@ PRESERVE8/g;
+
+    # Strip PROC and ENDPROC
+    s/\bPROC\b/@/g;
+    s/\bENDP\b/@/g;
+
+    # EQU directive
+    s/(.*)EQU(.*)/.set $1, $2/;
+
+    # Begin macro definition
+    if (/\bMACRO\b/)
+    {
+        # Process next line down, which will be the macro definition
+        $_ = <STDIN>;
+
+        $trimmed = trim($_);
+
+        # remove commas that are separating list
+        $trimmed =~ s/,//g;
+
+        # string to array
+        @incoming_array = split(/\s+/, $trimmed);
+
+        print ".macro @incoming_array[0]\n";
+
+        # remove the first element, as that is the name of the macro
+        shift (@incoming_array);
+
+        @macro_aliases{@incoming_array} = @mapping_list;
+
+        next;
+    }
+
+    while (($key, $value) = each(%macro_aliases))
+    {
+        $key =~ s/\$/\\\$/;
+        s/$key\b/$value/g;
+    }
+
+    # For macros, use \ to reference formal params
+#   s/\$/\\/g;                  # End macro definition
+    s/\bMEND\b/.endm/;              # No need to tell it where to stop assembling
+    next if /^\s*END\s*$/;
+
+    # Clang used by Chromium differs slightly from clang in XCode in what it
+    # will accept in the assembly.
+    if ($chromium) {
+        s/qsubaddx/qsax/i;
+        s/qaddsubx/qasx/i;
+        s/ldrneb/ldrbne/i;
+        s/ldrneh/ldrhne/i;
+        s/(vqshrun\.s16 .*, \#)0$/${1}8/i;
+
+        # http://llvm.org/bugs/show_bug.cgi?id=16022
+        s/\.include/#include/;
+    }
+
+    print;
+}
diff --git a/src/third_party/libvpx/build/make/armlink_adapter.sh b/src/third_party/libvpx/build/make/armlink_adapter.sh
new file mode 100755
index 0000000..75c342e
--- /dev/null
+++ b/src/third_party/libvpx/build/make/armlink_adapter.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+verbose=0
+set -- $*
+for i; do
+    if [ "$i" = "-o" ]; then
+        on_of=1
+    elif [ "$i" = "-v" ]; then
+        verbose=1
+    elif [ "$i" = "-g" ]; then
+        args="${args} --debug"
+    elif [ "$on_of" = "1" ]; then
+        outfile=$i
+        on_of=0
+    elif [ -f "$i" ]; then
+        infiles="$infiles $i"
+    elif [ "${i#-l}" != "$i" ]; then
+        libs="$libs ${i#-l}"
+    elif [ "${i#-L}" != "$i" ]; then
+        libpaths="${libpaths} ${i#-L}"
+    else
+        args="${args} ${i}"
+    fi
+    shift
+done
+
+# Absolutize library file names
+for f in $libs; do
+    found=0
+    for d in $libpaths; do
+        [ -f "$d/$f" ] && infiles="$infiles $d/$f" && found=1 && break
+        [ -f "$d/lib${f}.so" ] && infiles="$infiles $d/lib${f}.so" && found=1 && break
+        [ -f "$d/lib${f}.a" ] && infiles="$infiles $d/lib${f}.a" && found=1 && break
+    done
+    [ $found -eq 0 ] && infiles="$infiles $f"
+done
+for d in $libpaths; do
+    [ -n "$libsearchpath" ] && libsearchpath="${libsearchpath},"
+    libsearchpath="${libsearchpath}$d"
+done
+
+cmd="armlink $args --userlibpath=$libsearchpath --output=$outfile $infiles"
+[ $verbose -eq 1 ] && echo $cmd
+$cmd
diff --git a/src/third_party/libvpx/build/make/configure.sh b/src/third_party/libvpx/build/make/configure.sh
new file mode 100644
index 0000000..c738504
--- /dev/null
+++ b/src/third_party/libvpx/build/make/configure.sh
@@ -0,0 +1,1605 @@
+#!/bin/sh
+##
+##  configure.sh
+##
+##  This script is sourced by the main configure script and contains
+##  utility functions and other common bits that aren't strictly libvpx
+##  related.
+##
+##  This build system is based in part on the FFmpeg configure script.
+##
+
+
+#
+# Logging / Output Functions
+#
+die_unknown(){
+  echo "Unknown option \"$1\"."
+  echo "See $0 --help for available options."
+  clean_temp_files
+  exit 1
+}
+
+die() {
+  echo "$@"
+  echo
+  echo "Configuration failed. This could reflect a misconfiguration of your"
+  echo "toolchains, improper options selected, or another problem. If you"
+  echo "don't see any useful error messages above, the next step is to look"
+  echo "at the configure error log file ($logfile) to determine what"
+  echo "configure was trying to do when it died."
+  clean_temp_files
+  exit 1
+}
+
+log(){
+  echo "$@" >>$logfile
+}
+
+log_file(){
+  log BEGIN $1
+  cat -n $1 >>$logfile
+  log END $1
+}
+
+log_echo() {
+  echo "$@"
+  log "$@"
+}
+
+fwrite () {
+  outfile=$1
+  shift
+  echo "$@" >> ${outfile}
+}
+
+show_help_pre(){
+  for opt in ${CMDLINE_SELECT}; do
+    opt2=`echo $opt | sed -e 's;_;-;g'`
+    if enabled $opt; then
+      eval "toggle_${opt}=\"--disable-${opt2}\""
+    else
+      eval "toggle_${opt}=\"--enable-${opt2} \""
+    fi
+  done
+
+  cat <<EOF
+Usage: configure [options]
+Options:
+
+Build options:
+  --help                      print this message
+  --log=yes|no|FILE           file configure log is written to [config.log]
+  --target=TARGET             target platform tuple [generic-gnu]
+  --cpu=CPU                   optimize for a specific cpu rather than a family
+  --extra-cflags=ECFLAGS      add ECFLAGS to CFLAGS [$CFLAGS]
+  --extra-cxxflags=ECXXFLAGS  add ECXXFLAGS to CXXFLAGS [$CXXFLAGS]
+  ${toggle_extra_warnings}    emit harmless warnings (always non-fatal)
+  ${toggle_werror}            treat warnings as errors, if possible
+                              (not available with all compilers)
+  ${toggle_optimizations}     turn on/off compiler optimization flags
+  ${toggle_pic}               turn on/off Position Independent Code
+  ${toggle_ccache}            turn on/off compiler cache
+  ${toggle_debug}             enable/disable debug mode
+  ${toggle_gprof}             enable/disable gprof profiling instrumentation
+  ${toggle_gcov}              enable/disable gcov coverage instrumentation
+  ${toggle_thumb}             enable/disable building arm assembly in thumb mode
+  ${toggle_dependency_tracking}
+                              disable to speed up one-time build
+
+Install options:
+  ${toggle_install_docs}      control whether docs are installed
+  ${toggle_install_bins}      control whether binaries are installed
+  ${toggle_install_libs}      control whether libraries are installed
+  ${toggle_install_srcs}      control whether sources are installed
+
+
+EOF
+}
+
+show_help_post(){
+  cat <<EOF
+
+
+NOTES:
+    Object files are built at the place where configure is launched.
+
+    All boolean options can be negated. The default value is the opposite
+    of that shown above. If the option --disable-foo is listed, then
+    the default value for foo is enabled.
+
+Supported targets:
+EOF
+  show_targets ${all_platforms}
+  echo
+  exit 1
+}
+
+show_targets() {
+  while [ -n "$*" ]; do
+    if [ "${1%%-*}" = "${2%%-*}" ]; then
+      if [ "${2%%-*}" = "${3%%-*}" ]; then
+        printf "    %-24s %-24s %-24s\n" "$1" "$2" "$3"
+        shift; shift; shift
+      else
+        printf "    %-24s %-24s\n" "$1" "$2"
+        shift; shift
+      fi
+    else
+      printf "    %-24s\n" "$1"
+      shift
+    fi
+  done
+}
+
+show_help() {
+  show_help_pre
+  show_help_post
+}
+
+#
+# List Processing Functions
+#
+set_all(){
+  value=$1
+  shift
+  for var in $*; do
+    eval $var=$value
+  done
+}
+
+is_in(){
+  value=$1
+  shift
+  for var in $*; do
+    [ $var = $value ] && return 0
+  done
+  return 1
+}
+
+add_cflags() {
+  CFLAGS="${CFLAGS} $@"
+  CXXFLAGS="${CXXFLAGS} $@"
+}
+
+add_cflags_only() {
+  CFLAGS="${CFLAGS} $@"
+}
+
+add_cxxflags_only() {
+  CXXFLAGS="${CXXFLAGS} $@"
+}
+
+add_ldflags() {
+  LDFLAGS="${LDFLAGS} $@"
+}
+
+add_asflags() {
+  ASFLAGS="${ASFLAGS} $@"
+}
+
+add_extralibs() {
+  extralibs="${extralibs} $@"
+}
+
+#
+# Boolean Manipulation Functions
+#
+
+enable_codec(){
+  enabled $1 || echo "  enabling $1"
+  set_all yes $1
+
+  is_in $1 vp8 vp9 vp10 && \
+    set_all yes $1_encoder && \
+    set_all yes $1_decoder
+}
+
+disable_codec(){
+  disabled $1 || echo "  disabling $1"
+  set_all no $1
+
+  is_in $1 vp8 vp9 vp10 && \
+    set_all no $1_encoder && \
+    set_all no $1_decoder
+}
+
+enable_feature(){
+  set_all yes $*
+}
+
+disable_feature(){
+  set_all no $*
+}
+
+enabled(){
+  eval test "x\$$1" = "xyes"
+}
+
+disabled(){
+  eval test "x\$$1" = "xno"
+}
+
+# Iterates through positional parameters, checks to confirm the parameter has
+# not been explicitly (force) disabled, and enables the setting controlled by
+# the parameter when the setting is not disabled.
+# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS).
+soft_enable() {
+  for var in $*; do
+    if ! disabled $var; then
+      enabled $var || log_echo "  enabling $var"
+      enable_feature $var
+    fi
+  done
+}
+
+# Iterates through positional parameters, checks to confirm the parameter has
+# not been explicitly (force) enabled, and disables the setting controlled by
+# the parameter when the setting is not enabled.
+# Note: Does NOT alter RTCD generation options ($RTCD_OPTIONS).
+soft_disable() {
+  for var in $*; do
+    if ! enabled $var; then
+      disabled $var || log_echo "  disabling $var"
+      disable_feature $var
+    fi
+  done
+}
+
+#
+# Text Processing Functions
+#
+toupper(){
+  echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
+}
+
+tolower(){
+  echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
+}
+
+#
+# Temporary File Functions
+#
+source_path=${0%/*}
+enable_feature source_path_used
+if [ -z "$source_path" ] || [ "$source_path" = "." ]; then
+  # rjogrady: Hack for Cygwin / PS4 interaction.
+  # PS4 compiler doesn't understand cygdrive.
+  #source_path="`pwd`"
+  source_path='.'
+  disable_feature source_path_used
+fi
+
+if test ! -z "$TMPDIR" ; then
+  TMPDIRx="${TMPDIR}"
+elif test ! -z "$TEMPDIR" ; then
+  TMPDIRx="${TEMPDIR}"
+else
+  TMPDIRx="/tmp"
+fi
+RAND=$(awk 'BEGIN { srand(); printf "%d\n",(rand() * 32768)}')
+TMP_H="${TMPDIRx}/vpx-conf-$$-${RAND}.h"
+TMP_C="${TMPDIRx}/vpx-conf-$$-${RAND}.c"
+TMP_CC="${TMPDIRx}/vpx-conf-$$-${RAND}.cc"
+TMP_O="${TMPDIRx}/vpx-conf-$$-${RAND}.o"
+TMP_X="${TMPDIRx}/vpx-conf-$$-${RAND}.x"
+TMP_ASM="${TMPDIRx}/vpx-conf-$$-${RAND}.asm"
+
+clean_temp_files() {
+  rm -f ${TMP_C} ${TMP_CC} ${TMP_H} ${TMP_O} ${TMP_X} ${TMP_ASM}
+  enabled gcov && rm -f ${TMP_C%.c}.gcno ${TMP_CC%.cc}.gcno
+}
+
+#
+# Toolchain Check Functions
+#
+check_cmd() {
+  enabled external_build && return
+  log "$@"
+  "$@" >>${logfile} 2>&1
+}
+
+check_cc() {
+  log check_cc "$@"
+  cat >${TMP_C}
+  log_file ${TMP_C}
+  check_cmd ${CC} ${CFLAGS} "$@" -c -o ${TMP_O} ${TMP_C}
+}
+
+check_cxx() {
+  log check_cxx "$@"
+  cat >${TMP_CC}
+  log_file ${TMP_CC}
+  check_cmd ${CXX} ${CXXFLAGS} "$@" -c -o ${TMP_O} ${TMP_CC}
+}
+
+check_cpp() {
+  log check_cpp "$@"
+  cat > ${TMP_C}
+  log_file ${TMP_C}
+  check_cmd ${CC} ${CFLAGS} "$@" -E -o ${TMP_O} ${TMP_C}
+}
+
+check_ld() {
+  log check_ld "$@"
+  check_cc $@ \
+    && check_cmd ${LD} ${LDFLAGS} "$@" -o ${TMP_X} ${TMP_O} ${extralibs}
+}
+
+check_header(){
+  log check_header "$@"
+  header=$1
+  shift
+  var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
+  disable_feature $var
+  check_cpp "$@" <<EOF && enable_feature $var
+#include "$header"
+int x;
+EOF
+}
+
+check_cflags() {
+ log check_cflags "$@"
+ check_cc -Werror "$@" <<EOF
+int x;
+EOF
+}
+
+check_cxxflags() {
+  log check_cxxflags "$@"
+
+  # Catch CFLAGS that trigger CXX warnings
+  case "$CXX" in
+    *c++-analyzer|*clang++|*g++*)
+      check_cxx -Werror "$@" <<EOF
+int x;
+EOF
+      ;;
+    *)
+      check_cxx -Werror "$@" <<EOF
+int x;
+EOF
+      ;;
+    esac
+}
+
+check_add_cflags() {
+  check_cxxflags "$@" && add_cxxflags_only "$@"
+  check_cflags "$@" && add_cflags_only "$@"
+}
+
+check_add_cxxflags() {
+  check_cxxflags "$@" && add_cxxflags_only "$@"
+}
+
+check_add_asflags() {
+  log add_asflags "$@"
+  add_asflags "$@"
+}
+
+check_add_ldflags() {
+  log add_ldflags "$@"
+  add_ldflags "$@"
+}
+
+check_asm_align() {
+  log check_asm_align "$@"
+  cat >${TMP_ASM} <<EOF
+section .rodata
+align 16
+EOF
+  log_file ${TMP_ASM}
+  check_cmd ${AS} ${ASFLAGS} -o ${TMP_O} ${TMP_ASM}
+  readelf -WS ${TMP_O} >${TMP_X}
+  log_file ${TMP_X}
+  if ! grep -q '\.rodata .* 16$' ${TMP_X}; then
+    die "${AS} ${ASFLAGS} does not support section alignment (nasm <=2.08?)"
+  fi
+}
+
+# tests for -m$1 toggling the feature given in $2. If $2 is empty $1 is used.
+check_gcc_machine_option() {
+  opt="$1"
+  feature="$2"
+  [ -n "$feature" ] || feature="$opt"
+
+  if enabled gcc && ! disabled "$feature" && ! check_cflags "-m$opt"; then
+    RTCD_OPTIONS="${RTCD_OPTIONS}--disable-$feature "
+  else
+    soft_enable "$feature"
+  fi
+}
+
+write_common_config_banner() {
+  print_webm_license config.mk "##" ""
+  echo '# This file automatically generated by configure. Do not edit!' >> config.mk
+  echo "TOOLCHAIN := ${toolchain}" >> config.mk
+
+  case ${toolchain} in
+    *-linux-rvct)
+      echo "ALT_LIBC := ${alt_libc}" >> config.mk
+      ;;
+  esac
+}
+
+write_common_config_targets() {
+  for t in ${all_targets}; do
+    if enabled ${t}; then
+      if enabled child; then
+        fwrite config.mk "ALL_TARGETS += ${t}-${toolchain}"
+      else
+        fwrite config.mk "ALL_TARGETS += ${t}"
+      fi
+    fi
+    true;
+  done
+  true
+}
+
+write_common_target_config_mk() {
+  saved_CC="${CC}"
+  saved_CXX="${CXX}"
+  enabled ccache && CC="ccache ${CC}"
+  enabled ccache && CXX="ccache ${CXX}"
+  print_webm_license $1 "##" ""
+
+  cat >> $1 << EOF
+# This file automatically generated by configure. Do not edit!
+SRC_PATH="$source_path"
+SRC_PATH_BARE=$source_path
+BUILD_PFX=${BUILD_PFX}
+TOOLCHAIN=${toolchain}
+ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl}
+GEN_VCPROJ=${gen_vcproj_cmd}
+MSVS_ARCH_DIR=${msvs_arch_dir}
+
+CC=${CC}
+CXX=${CXX}
+AR=${AR}
+LD=${LD}
+AS=${AS}
+STRIP=${STRIP}
+NM=${NM}
+
+CFLAGS  = ${CFLAGS}
+CXXFLAGS  = ${CXXFLAGS}
+ARFLAGS = -crs\$(if \$(quiet),,v)
+LDFLAGS = ${LDFLAGS}
+ASFLAGS = ${ASFLAGS}
+extralibs = ${extralibs}
+AS_SFX    = ${AS_SFX:-.asm}
+EXE_SFX   = ${EXE_SFX}
+VCPROJ_SFX = ${VCPROJ_SFX}
+RTCD_OPTIONS = ${RTCD_OPTIONS}
+EOF
+
+  if enabled rvct; then cat >> $1 << EOF
+fmt_deps = sed -e 's;^__image.axf;\${@:.d=.o} \$@;' #hide
+EOF
+elif enabled orbis; then cat >> $1 << EOF
+fmt_deps = python fix_orbis_deps.py
+EOF
+  else cat >> $1 << EOF
+fmt_deps = sed -e 's;^\([a-zA-Z0-9_]*\)\.o;\${@:.d=.o} \$@;'
+EOF
+  fi
+
+  print_config_mk ARCH   "${1}" ${ARCH_LIST}
+  print_config_mk HAVE   "${1}" ${HAVE_LIST}
+  print_config_mk CONFIG "${1}" ${CONFIG_LIST}
+  print_config_mk HAVE   "${1}" gnu_strip
+
+  enabled msvs && echo "CONFIG_VS_VERSION=${vs_version}" >> "${1}"
+
+  CC="${saved_CC}"
+  CXX="${saved_CXX}"
+}
+
+write_common_target_config_h() {
+  print_webm_license ${TMP_H} "/*" " */"
+  cat >> ${TMP_H} << EOF
+/* This file automatically generated by configure. Do not edit! */
+#ifndef VPX_CONFIG_H
+#define VPX_CONFIG_H
+#define RESTRICT    ${RESTRICT}
+#define INLINE      ${INLINE}
+EOF
+  print_config_h ARCH   "${TMP_H}" ${ARCH_LIST}
+  print_config_h HAVE   "${TMP_H}" ${HAVE_LIST}
+  print_config_h CONFIG "${TMP_H}" ${CONFIG_LIST}
+  print_config_vars_h   "${TMP_H}" ${VAR_LIST}
+  echo "#endif /* VPX_CONFIG_H */" >> ${TMP_H}
+  mkdir -p `dirname "$1"`
+  cmp "$1" ${TMP_H} >/dev/null 2>&1 || mv ${TMP_H} "$1"
+}
+
+process_common_cmdline() {
+  for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+      --child)
+        enable_feature child
+        ;;
+      --log*)
+        logging="$optval"
+        if ! disabled logging ; then
+          enabled logging || logfile="$logging"
+        else
+          logfile=/dev/null
+        fi
+        ;;
+      --target=*)
+        toolchain="${toolchain:-${optval}}"
+        ;;
+      --force-target=*)
+        toolchain="${toolchain:-${optval}}"
+        enable_feature force_toolchain
+        ;;
+      --cpu=*)
+        tune_cpu="$optval"
+        ;;
+      --extra-cflags=*)
+        extra_cflags="${optval}"
+        ;;
+      --extra-cxxflags=*)
+        extra_cxxflags="${optval}"
+        ;;
+      --enable-?*|--disable-?*)
+        eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
+        if is_in ${option} ${ARCH_EXT_LIST}; then
+          [ $action = "disable" ] && RTCD_OPTIONS="${RTCD_OPTIONS}--disable-${option} "
+        elif [ $action = "disable" ] && ! disabled $option ; then
+          is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt
+          log_echo "  disabling $option"
+        elif [ $action = "enable" ] && ! enabled $option ; then
+          is_in ${option} ${CMDLINE_SELECT} || die_unknown $opt
+          log_echo "  enabling $option"
+        fi
+        ${action}_feature $option
+        ;;
+      --require-?*)
+        eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
+        if is_in ${option} ${ARCH_EXT_LIST}; then
+            RTCD_OPTIONS="${RTCD_OPTIONS}${opt} "
+        else
+            die_unknown $opt
+        fi
+        ;;
+      --force-enable-?*|--force-disable-?*)
+        eval `echo "$opt" | sed 's/--force-/action=/;s/-/ option=/;s/-/_/g'`
+        ${action}_feature $option
+        ;;
+      --libc=*)
+        [ -d "${optval}" ] || die "Not a directory: ${optval}"
+        disable_feature builtin_libc
+        alt_libc="${optval}"
+        ;;
+      --as=*)
+        [ "${optval}" = yasm ] || [ "${optval}" = nasm ] \
+          || [ "${optval}" = auto ] \
+          || die "Must be yasm, nasm or auto: ${optval}"
+        alt_as="${optval}"
+        ;;
+      --size-limit=*)
+        w="${optval%%x*}"
+        h="${optval##*x}"
+        VAR_LIST="DECODE_WIDTH_LIMIT ${w} DECODE_HEIGHT_LIMIT ${h}"
+        [ ${w} -gt 0 ] && [ ${h} -gt 0 ] || die "Invalid size-limit: too small."
+        [ ${w} -lt 65536 ] && [ ${h} -lt 65536 ] \
+            || die "Invalid size-limit: too big."
+        enable_feature size_limit
+        ;;
+      --prefix=*)
+        prefix="${optval}"
+        ;;
+      --libdir=*)
+        libdir="${optval}"
+        ;;
+      --sdk-path=*)
+        [ -d "${optval}" ] || die "Not a directory: ${optval}"
+        sdk_path="${optval}"
+        ;;
+      --libc|--as|--prefix|--libdir|--sdk-path)
+        die "Option ${opt} requires argument"
+        ;;
+      --help|-h)
+        show_help
+        ;;
+      *)
+        die_unknown $opt
+        ;;
+    esac
+  done
+}
+
+process_cmdline() {
+  for opt do
+    optval="${opt#*=}"
+    case "$opt" in
+      *)
+        process_common_cmdline $opt
+        ;;
+    esac
+  done
+}
+
+post_process_common_cmdline() {
+  prefix="${prefix:-/usr/local}"
+  prefix="${prefix%/}"
+  libdir="${libdir:-${prefix}/lib}"
+  libdir="${libdir%/}"
+  if [ "${libdir#${prefix}}" = "${libdir}" ]; then
+    die "Libdir ${libdir} must be a subdirectory of ${prefix}"
+  fi
+}
+
+post_process_cmdline() {
+  true;
+}
+
+setup_gnu_toolchain() {
+  CC=${CC:-${CROSS}gcc}
+  CXX=${CXX:-${CROSS}g++}
+  AR=${AR:-${CROSS}ar}
+  LD=${LD:-${CROSS}${link_with_cc:-ld}}
+  AS=${AS:-${CROSS}as}
+  STRIP=${STRIP:-${CROSS}strip}
+  NM=${NM:-${CROSS}nm}
+  AS_SFX=.s
+  EXE_SFX=
+}
+
+setup_clang_toolchain() {
+  CC=${CC:-${CROSS}clang}
+  CXX=${CXX:-${CROSS}clang++}
+  AR=${AR:-${CROSS}ar}
+  LD=${LD:-${CROSS}ld}
+  AS=${AS:-${CROSS}as}
+  STRIP=${STRIP:-${CROSS}strip}
+  NM=${NM:-${CROSS}nm}
+  AS_SFX=.s
+  EXE_SFX=
+}
+
+# Reliably find the newest available Darwin SDKs. (Older versions of
+# xcrun don't support --show-sdk-path.)
+show_darwin_sdk_path() {
+  xcrun --sdk $1 --show-sdk-path 2>/dev/null ||
+    xcodebuild -sdk $1 -version Path 2>/dev/null
+}
+
+# Print the major version number of the Darwin SDK specified by $1.
+show_darwin_sdk_major_version() {
+  xcrun --sdk $1 --show-sdk-version 2>/dev/null | cut -d. -f1
+}
+
+# Print the Xcode version.
+show_xcode_version() {
+  xcodebuild -version | head -n1 | cut -d' ' -f2
+}
+
+# Fails when Xcode version is less than 6.3.
+check_xcode_minimum_version() {
+  xcode_major=$(show_xcode_version | cut -f1 -d.)
+  xcode_minor=$(show_xcode_version | cut -f2 -d.)
+  xcode_min_major=6
+  xcode_min_minor=3
+  if [ ${xcode_major} -lt ${xcode_min_major} ]; then
+    return 1
+  fi
+  if [ ${xcode_major} -eq ${xcode_min_major} ] \
+    && [ ${xcode_minor} -lt ${xcode_min_minor} ]; then
+    return 1
+  fi
+}
+
+process_common_toolchain() {
+  if [ -z "$toolchain" ]; then
+    gcctarget="${CHOST:-$(gcc -dumpmachine 2> /dev/null)}"
+
+    # detect tgt_isa
+    case "$gcctarget" in
+      aarch64*)
+        tgt_isa=arm64
+        ;;
+      armv6*)
+        tgt_isa=armv6
+        ;;
+      armv7*-hardfloat* | armv7*-gnueabihf | arm-*-gnueabihf)
+        tgt_isa=armv7
+        float_abi=hard
+        ;;
+      armv7*)
+        tgt_isa=armv7
+        float_abi=softfp
+        ;;
+      *x86_64*|*amd64*)
+        tgt_isa=x86_64
+        ;;
+      *i[3456]86*)
+        tgt_isa=x86
+        ;;
+      *sparc*)
+        tgt_isa=sparc
+        ;;
+    esac
+
+    # detect tgt_os
+    case "$gcctarget" in
+      *darwin10*)
+        tgt_isa=x86_64
+        tgt_os=darwin10
+        ;;
+      *darwin11*)
+        tgt_isa=x86_64
+        tgt_os=darwin11
+        ;;
+      *darwin12*)
+        tgt_isa=x86_64
+        tgt_os=darwin12
+        ;;
+      *darwin13*)
+        tgt_isa=x86_64
+        tgt_os=darwin13
+        ;;
+      *darwin14*)
+        tgt_isa=x86_64
+        tgt_os=darwin14
+        ;;
+      *darwin15*)
+        tgt_isa=x86_64
+        tgt_os=darwin15
+        ;;
+      x86_64*mingw32*)
+        tgt_os=win64
+        ;;
+      *mingw32*|*cygwin*)
+        [ -z "$tgt_isa" ] && tgt_isa=x86
+        tgt_os=win32
+        ;;
+      *linux*|*bsd*)
+        tgt_os=linux
+        ;;
+      *solaris2.10)
+        tgt_os=solaris
+        ;;
+      *os2*)
+        tgt_os=os2
+        ;;
+    esac
+
+    if [ -n "$tgt_isa" ] && [ -n "$tgt_os" ]; then
+      toolchain=${tgt_isa}-${tgt_os}-gcc
+    fi
+  fi
+
+  toolchain=${toolchain:-generic-gnu}
+
+  is_in ${toolchain} ${all_platforms} || enabled force_toolchain \
+    || die "Unrecognized toolchain '${toolchain}'"
+
+  enabled child || log_echo "Configuring for target '${toolchain}'"
+
+  #
+  # Set up toolchain variables
+  #
+  tgt_isa=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $1}')
+  tgt_os=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $2}')
+  tgt_cc=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $3}')
+
+  # Mark the specific ISA requested as enabled
+  soft_enable ${tgt_isa}
+  enable_feature ${tgt_os}
+  enable_feature ${tgt_cc}
+
+  # Enable the architecture family
+  case ${tgt_isa} in
+    arm*)
+      enable_feature arm
+      ;;
+    mips*)
+      enable_feature mips
+      ;;
+  esac
+
+  # PIC is probably what we want when building shared libs
+  enabled shared && soft_enable pic
+  enabled orbis && soft_enable pic
+
+  # Minimum iOS version for all target platforms (darwin and iphonesimulator).
+  # Shared library framework builds are only possible on iOS 8 and later.
+  if enabled shared; then
+    IOS_VERSION_OPTIONS="--enable-shared"
+    IOS_VERSION_MIN="8.0"
+  else
+    IOS_VERSION_OPTIONS=""
+    IOS_VERSION_MIN="6.0"
+  fi
+
+  # Handle darwin variants. Newer SDKs allow targeting older
+  # platforms, so use the newest one available.
+  case ${toolchain} in
+    arm*-darwin*)
+      add_cflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
+      iphoneos_sdk_dir="$(show_darwin_sdk_path iphoneos)"
+      if [ -d "${iphoneos_sdk_dir}" ]; then
+        add_cflags  "-isysroot ${iphoneos_sdk_dir}"
+        add_ldflags "-isysroot ${iphoneos_sdk_dir}"
+      fi
+      ;;
+    x86*-darwin*)
+      osx_sdk_dir="$(show_darwin_sdk_path macosx)"
+      if [ -d "${osx_sdk_dir}" ]; then
+        add_cflags  "-isysroot ${osx_sdk_dir}"
+        add_ldflags "-isysroot ${osx_sdk_dir}"
+      fi
+      ;;
+  esac
+
+  case ${toolchain} in
+    *-darwin8-*)
+      add_cflags  "-mmacosx-version-min=10.4"
+      add_ldflags "-mmacosx-version-min=10.4"
+      ;;
+    *-darwin9-*)
+      add_cflags  "-mmacosx-version-min=10.5"
+      add_ldflags "-mmacosx-version-min=10.5"
+      ;;
+    *-darwin10-*)
+      add_cflags  "-mmacosx-version-min=10.6"
+      add_ldflags "-mmacosx-version-min=10.6"
+      ;;
+    *-darwin11-*)
+      add_cflags  "-mmacosx-version-min=10.7"
+      add_ldflags "-mmacosx-version-min=10.7"
+      ;;
+    *-darwin12-*)
+      add_cflags  "-mmacosx-version-min=10.8"
+      add_ldflags "-mmacosx-version-min=10.8"
+      ;;
+    *-darwin13-*)
+      add_cflags  "-mmacosx-version-min=10.9"
+      add_ldflags "-mmacosx-version-min=10.9"
+      ;;
+    *-darwin14-*)
+      add_cflags  "-mmacosx-version-min=10.10"
+      add_ldflags "-mmacosx-version-min=10.10"
+      ;;
+    *-darwin15-*)
+      add_cflags  "-mmacosx-version-min=10.11"
+      add_ldflags "-mmacosx-version-min=10.11"
+      ;;
+    *-iphonesimulator-*)
+      add_cflags  "-miphoneos-version-min=${IOS_VERSION_MIN}"
+      add_ldflags "-miphoneos-version-min=${IOS_VERSION_MIN}"
+      iossim_sdk_dir="$(show_darwin_sdk_path iphonesimulator)"
+      if [ -d "${iossim_sdk_dir}" ]; then
+        add_cflags  "-isysroot ${iossim_sdk_dir}"
+        add_ldflags "-isysroot ${iossim_sdk_dir}"
+      fi
+      ;;
+  esac
+
+  # Handle Solaris variants. Solaris 10 needs -lposix4
+  case ${toolchain} in
+    sparc-solaris-*)
+      add_extralibs -lposix4
+      ;;
+    *-solaris-*)
+      add_extralibs -lposix4
+      ;;
+  esac
+
+  # Process ARM architecture variants
+  case ${toolchain} in
+    arm*)
+      # on arm, isa versions are supersets
+      case ${tgt_isa} in
+        arm64|armv8)
+          soft_enable neon
+          ;;
+        armv7|armv7s)
+          soft_enable neon
+          # Only enable neon_asm when neon is also enabled.
+          enabled neon && soft_enable neon_asm
+          # If someone tries to force it through, die.
+          if disabled neon && enabled neon_asm; then
+            die "Disabling neon while keeping neon-asm is not supported"
+          fi
+          case ${toolchain} in
+            # Apple iOS SDKs no longer support armv6 as of the version 9
+            # release (coincides with release of Xcode 7). Only enable media
+            # when using earlier SDK releases.
+            *-darwin*)
+              if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
+                soft_enable media
+              else
+                soft_disable media
+                RTCD_OPTIONS="${RTCD_OPTIONS}--disable-media "
+              fi
+              ;;
+            *)
+              soft_enable media
+              ;;
+          esac
+          ;;
+        armv6)
+          case ${toolchain} in
+            *-darwin*)
+              if [ "$(show_darwin_sdk_major_version iphoneos)" -lt 9 ]; then
+                soft_enable media
+              else
+                die "Your iOS SDK does not support armv6."
+              fi
+              ;;
+            *)
+              soft_enable media
+              ;;
+          esac
+          ;;
+      esac
+
+      asm_conversion_cmd="cat"
+
+      case ${tgt_cc} in
+        gcc)
+          link_with_cc=gcc
+          setup_gnu_toolchain
+          arch_int=${tgt_isa##armv}
+          arch_int=${arch_int%%te}
+          check_add_asflags --defsym ARCHITECTURE=${arch_int}
+          tune_cflags="-mtune="
+          if [ ${tgt_isa} = "armv7" ] || [ ${tgt_isa} = "armv7s" ]; then
+            if [ -z "${float_abi}" ]; then
+              check_cpp <<EOF && float_abi=hard || float_abi=softfp
+#ifndef __ARM_PCS_VFP
+#error "not hardfp"
+#endif
+EOF
+            fi
+            check_add_cflags  -march=armv7-a -mfloat-abi=${float_abi}
+            check_add_asflags -march=armv7-a -mfloat-abi=${float_abi}
+
+            if enabled neon || enabled neon_asm; then
+              check_add_cflags -mfpu=neon #-ftree-vectorize
+              check_add_asflags -mfpu=neon
+            fi
+          else
+            check_add_cflags -march=${tgt_isa}
+            check_add_asflags -march=${tgt_isa}
+          fi
+
+          enabled debug && add_asflags -g
+          asm_conversion_cmd="${source_path}/build/make/ads2gas.pl"
+          if enabled thumb; then
+            asm_conversion_cmd="$asm_conversion_cmd -thumb"
+            check_add_cflags -mthumb
+            check_add_asflags -mthumb -mimplicit-it=always
+          fi
+          ;;
+        vs*)
+          asm_conversion_cmd="${source_path}/build/make/ads2armasm_ms.pl"
+          AS_SFX=.s
+          msvs_arch_dir=arm-msvs
+          disable_feature multithread
+          disable_feature unit_tests
+          vs_version=${tgt_cc##vs}
+          if [ $vs_version -ge 12 ]; then
+            # MSVC 2013 doesn't allow doing plain .exe projects for ARM,
+            # only "AppContainerApplication" which requires an AppxManifest.
+            # Therefore disable the examples, just build the library.
+            disable_feature examples
+          fi
+          ;;
+        rvct)
+          CC=armcc
+          AR=armar
+          AS=armasm
+          LD="${source_path}/build/make/armlink_adapter.sh"
+          STRIP=arm-none-linux-gnueabi-strip
+          NM=arm-none-linux-gnueabi-nm
+          tune_cflags="--cpu="
+          tune_asflags="--cpu="
+          if [ -z "${tune_cpu}" ]; then
+            if [ ${tgt_isa} = "armv7" ]; then
+              if enabled neon || enabled neon_asm
+              then
+                check_add_cflags --fpu=softvfp+vfpv3
+                check_add_asflags --fpu=softvfp+vfpv3
+              fi
+              check_add_cflags --cpu=Cortex-A8
+              check_add_asflags --cpu=Cortex-A8
+            else
+              check_add_cflags --cpu=${tgt_isa##armv}
+              check_add_asflags --cpu=${tgt_isa##armv}
+            fi
+          fi
+          arch_int=${tgt_isa##armv}
+          arch_int=${arch_int%%te}
+          check_add_asflags --pd "\"ARCHITECTURE SETA ${arch_int}\""
+          enabled debug && add_asflags -g
+          add_cflags --gnu
+          add_cflags --enum_is_int
+          add_cflags --wchar32
+          ;;
+      esac
+
+      case ${tgt_os} in
+        none*)
+          disable_feature multithread
+          disable_feature os_support
+          ;;
+
+        android*)
+          SDK_PATH=${sdk_path}
+          COMPILER_LOCATION=`find "${SDK_PATH}" \
+                             -name "arm-linux-androideabi-gcc*" -print -quit`
+          TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/arm-linux-androideabi-
+          CC=${TOOLCHAIN_PATH}gcc
+          CXX=${TOOLCHAIN_PATH}g++
+          AR=${TOOLCHAIN_PATH}ar
+          LD=${TOOLCHAIN_PATH}gcc
+          AS=${TOOLCHAIN_PATH}as
+          STRIP=${TOOLCHAIN_PATH}strip
+          NM=${TOOLCHAIN_PATH}nm
+
+          if [ -z "${alt_libc}" ]; then
+            alt_libc=`find "${SDK_PATH}" -name arch-arm -print | \
+              awk '{n = split($0,a,"/"); \
+                split(a[n-1],b,"-"); \
+                print $0 " " b[2]}' | \
+                sort -g -k 2 | \
+                awk '{ print $1 }' | tail -1`
+          fi
+
+          if [ -d "${alt_libc}" ]; then
+            add_cflags "--sysroot=${alt_libc}"
+            add_ldflags "--sysroot=${alt_libc}"
+          fi
+
+          # linker flag that routes around a CPU bug in some
+          # Cortex-A8 implementations (NDK Dev Guide)
+          add_ldflags "-Wl,--fix-cortex-a8"
+
+          enable_feature pic
+          soft_enable realtime_only
+          if [ ${tgt_isa} = "armv7" ]; then
+            soft_enable runtime_cpu_detect
+          fi
+          if enabled runtime_cpu_detect; then
+            add_cflags "-I${SDK_PATH}/sources/android/cpufeatures"
+          fi
+          ;;
+
+        darwin*)
+          XCRUN_FIND="xcrun --sdk iphoneos --find"
+          CXX="$(${XCRUN_FIND} clang++)"
+          CC="$(${XCRUN_FIND} clang)"
+          AR="$(${XCRUN_FIND} ar)"
+          AS="$(${XCRUN_FIND} as)"
+          STRIP="$(${XCRUN_FIND} strip)"
+          NM="$(${XCRUN_FIND} nm)"
+          RANLIB="$(${XCRUN_FIND} ranlib)"
+          AS_SFX=.s
+          LD="${CXX:-$(${XCRUN_FIND} ld)}"
+
+          # ASFLAGS is written here instead of using check_add_asflags
+          # because we need to overwrite all of ASFLAGS and purge the
+          # options that were put in above
+          ASFLAGS="-arch ${tgt_isa} -g"
+
+          add_cflags -arch ${tgt_isa}
+          add_ldflags -arch ${tgt_isa}
+
+          alt_libc="$(show_darwin_sdk_path iphoneos)"
+          if [ -d "${alt_libc}" ]; then
+            add_cflags -isysroot ${alt_libc}
+          fi
+
+          if [ "${LD}" = "${CXX}" ]; then
+            add_ldflags -miphoneos-version-min="${IOS_VERSION_MIN}"
+          else
+            add_ldflags -ios_version_min "${IOS_VERSION_MIN}"
+          fi
+
+          for d in lib usr/lib usr/lib/system; do
+            try_dir="${alt_libc}/${d}"
+            [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
+          done
+
+          case ${tgt_isa} in
+            armv7|armv7s|armv8|arm64)
+              if enabled neon && ! check_xcode_minimum_version; then
+                soft_disable neon
+                log_echo "  neon disabled: upgrade Xcode (need v6.3+)."
+                if enabled neon_asm; then
+                  soft_disable neon_asm
+                  log_echo "  neon_asm disabled: upgrade Xcode (need v6.3+)."
+                fi
+              fi
+              ;;
+          esac
+
+          asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl"
+
+          if [ "$(show_darwin_sdk_major_version iphoneos)" -gt 8 ]; then
+            check_add_cflags -fembed-bitcode
+            check_add_asflags -fembed-bitcode
+            check_add_ldflags -fembed-bitcode
+          fi
+          ;;
+
+        linux*)
+          enable_feature linux
+          if enabled rvct; then
+            # Check if we have CodeSourcery GCC in PATH. Needed for
+            # libraries
+            which arm-none-linux-gnueabi-gcc 2>&- || \
+              die "Couldn't find CodeSourcery GCC from PATH"
+
+            # Use armcc as a linker to enable translation of
+            # some gcc specific options such as -lm and -lpthread.
+            LD="armcc --translate_gcc"
+
+            # create configuration file (uses path to CodeSourcery GCC)
+            armcc --arm_linux_configure --arm_linux_config_file=arm_linux.cfg
+
+            add_cflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg
+            add_asflags --no_hide_all --apcs=/interwork
+            add_ldflags --arm_linux_paths --arm_linux_config_file=arm_linux.cfg
+            enabled pic && add_cflags --apcs=/fpic
+            enabled pic && add_asflags --apcs=/fpic
+            enabled shared && add_cflags --shared
+          fi
+          ;;
+      esac
+      ;;
+    mips*)
+      link_with_cc=gcc
+      setup_gnu_toolchain
+      tune_cflags="-mtune="
+      if enabled dspr2; then
+        check_add_cflags -mips32r2 -mdspr2
+      fi
+
+      if enabled runtime_cpu_detect; then
+        disable_feature runtime_cpu_detect
+      fi
+
+      if [ -n "${tune_cpu}" ]; then
+        case ${tune_cpu} in
+          p5600)
+            check_add_cflags -mips32r5 -funroll-loops -mload-store-pairs
+            check_add_cflags -msched-weight -mhard-float -mfp64
+            check_add_asflags -mips32r5 -mhard-float -mfp64
+            check_add_ldflags -mfp64
+            ;;
+          i6400)
+            check_add_cflags -mips64r6 -mabi=64 -funroll-loops -msched-weight
+            check_add_cflags  -mload-store-pairs -mhard-float -mfp64
+            check_add_asflags -mips64r6 -mabi=64 -mhard-float -mfp64
+            check_add_ldflags -mips64r6 -mabi=64 -mfp64
+            ;;
+        esac
+
+        if enabled msa; then
+          add_cflags -mmsa
+          add_asflags -mmsa
+          add_ldflags -mmsa
+        fi
+      fi
+
+      check_add_cflags -march=${tgt_isa}
+      check_add_asflags -march=${tgt_isa}
+      check_add_asflags -KPIC
+      ;;
+    x86*)
+      case  ${tgt_os} in
+        win*)
+          enabled gcc && add_cflags -fno-common
+          ;;
+        solaris*)
+          CC=${CC:-${CROSS}gcc}
+          CXX=${CXX:-${CROSS}g++}
+          LD=${LD:-${CROSS}gcc}
+          CROSS=${CROSS-g}
+          ;;
+        os2)
+          disable_feature pic
+          AS=${AS:-nasm}
+          add_ldflags -Zhigh-mem
+          ;;
+        orbis)
+          CROSS=${CROSS:-orbis-}
+          ;;
+      esac
+
+      AS="${alt_as:-${AS:-auto}}"
+      case  ${tgt_cc} in
+        icc*)
+          CC=${CC:-icc}
+          LD=${LD:-icc}
+          setup_gnu_toolchain
+          add_cflags -use-msasm  # remove -use-msasm too?
+          # add -no-intel-extensions to suppress warning #10237
+          # refer to http://software.intel.com/en-us/forums/topic/280199
+          add_ldflags -i-static -no-intel-extensions
+          enabled x86_64 && add_cflags -ipo -static -O3 -no-prec-div
+          enabled x86_64 && AR=xiar
+          case ${tune_cpu} in
+            atom*)
+              tune_cflags="-x"
+              tune_cpu="SSE3_ATOM"
+              ;;
+            *)
+              tune_cflags="-march="
+              ;;
+          esac
+          ;;
+        gcc*)
+          link_with_cc=gcc
+          tune_cflags="-march="
+          setup_gnu_toolchain
+          #for 32 bit x86 builds, -O3 did not turn on this flag
+          enabled optimizations && disabled gprof && check_add_cflags -fomit-frame-pointer
+          ;;
+        clang*)
+         link_with_cc=clang
+          tune_cflags="-march="
+          setup_clang_toolchain
+          ;;
+        vs*)
+          # When building with Microsoft Visual Studio the assembler is
+          # invoked directly. Checking at configure time is unnecessary.
+          # Skip the check by setting AS arbitrarily
+          AS=msvs
+          msvs_arch_dir=x86-msvs
+          vc_version=${tgt_cc##vs}
+          case $vc_version in
+            7|8|9|10)
+              echo "${tgt_cc} does not support avx/avx2, disabling....."
+              RTCD_OPTIONS="${RTCD_OPTIONS}--disable-avx --disable-avx2 "
+              soft_disable avx
+              soft_disable avx2
+              ;;
+          esac
+          case $vc_version in
+            7|8|9)
+              echo "${tgt_cc} omits stdint.h, disabling webm-io..."
+              soft_disable webm_io
+              ;;
+          esac
+          ;;
+      esac
+
+      bits=32
+      enabled x86_64 && bits=64
+      check_cpp <<EOF && bits=x32
+#if !defined(__ILP32__) || !defined(__x86_64__)
+#error "not x32"
+#endif
+EOF
+      case ${tgt_cc} in
+        gcc*)
+          add_cflags -m${bits}
+          add_ldflags -m${bits}
+          ;;
+      esac
+
+      disabled orbis && soft_enable runtime_cpu_detect
+      # We can't use 'check_cflags' until the compiler is configured and CC is
+      # populated.
+      for ext in ${ARCH_EXT_LIST_X86}; do
+        # disable higher order extensions to simplify asm dependencies
+        if [ "$disable_exts" = "yes" ]; then
+          if ! disabled $ext; then
+            RTCD_OPTIONS="${RTCD_OPTIONS}--disable-${ext} "
+            disable_feature $ext
+          fi
+        elif disabled $ext; then
+          disable_exts="yes"
+        elif [ "$ext" = "avx2" ]; then
+          # on orbis never enable avx2.
+          disabled orbis && check_gcc_machine_option ${ext%_*} $ext
+        else
+          # use the shortened version for the flag: sse4_1 -> sse4
+          check_gcc_machine_option ${ext%_*} $ext
+        fi
+      done
+
+      if enabled external_build; then
+        log_echo "  skipping assembler detection"
+      else
+        case "${AS}" in
+          auto|"")
+            which nasm >/dev/null 2>&1 && AS=nasm
+            which yasm >/dev/null 2>&1 && AS=yasm
+            if [ "${AS}" = nasm ] ; then
+              # Apple ships version 0.98 of nasm through at least Xcode 6. Revisit
+              # this check if they start shipping a compatible version.
+              apple=`nasm -v | grep "Apple"`
+              [ -n "${apple}" ] \
+                && echo "Unsupported version of nasm: ${apple}" \
+                && AS=""
+            fi
+            [ "${AS}" = auto ] || [ -z "${AS}" ] \
+              && die "Neither yasm nor nasm have been found." \
+                     "See the prerequisites section in the README for more info."
+            ;;
+        esac
+        log_echo "  using $AS"
+      fi
+      [ "${AS##*/}" = nasm ] && add_asflags -Ox
+      AS_SFX=.asm
+      case  ${tgt_os} in
+        win32)
+          add_asflags -f win32
+          enabled debug && add_asflags -g cv8
+          EXE_SFX=.exe
+          ;;
+        win64)
+          add_asflags -f x64
+          enabled debug && add_asflags -g cv8
+          EXE_SFX=.exe
+          ;;
+        linux*|solaris*|android*)
+          add_asflags -f elf${bits}
+          enabled debug && [ "${AS}" = yasm ] && add_asflags -g dwarf2
+          enabled debug && [ "${AS}" = nasm ] && add_asflags -g
+          [ "${AS##*/}" = nasm ] && check_asm_align
+          ;;
+        darwin*)
+          add_asflags -f macho${bits}
+          enabled x86 && darwin_arch="-arch i386" || darwin_arch="-arch x86_64"
+          add_cflags  ${darwin_arch}
+          add_ldflags ${darwin_arch}
+          # -mdynamic-no-pic is still a bit of voodoo -- it was required at
+          # one time, but does not seem to be now, and it breaks some of the
+          # code that still relies on inline assembly.
+          # enabled icc && ! enabled pic && add_cflags -fno-pic -mdynamic-no-pic
+          enabled icc && ! enabled pic && add_cflags -fno-pic
+          ;;
+        iphonesimulator)
+          add_asflags -f macho${bits}
+          enabled x86 && sim_arch="-arch i386" || sim_arch="-arch x86_64"
+          add_cflags  ${sim_arch}
+          add_ldflags ${sim_arch}
+
+          if [ "$(show_darwin_sdk_major_version iphonesimulator)" -gt 8 ]; then
+            # yasm v1.3.0 doesn't know what -fembed-bitcode means, so turning it
+            # on is pointless (unless building a C-only lib). Warn the user, but
+            # do nothing here.
+            log "Warning: Bitcode embed disabled for simulator targets."
+          fi
+          ;;
+        os2)
+          add_asflags -f aout
+          enabled debug && add_asflags -g
+          EXE_SFX=.exe
+          ;;
+        orbis*)
+          add_asflags -f elf${bits}
+          enabled debug && [ "${AS}" = yasm ] && add_asflags -g dwarf2
+          enabled debug && [ "${AS}" = nasm ] && add_asflags -g
+          [ "${AS##*/}" = nasm ] && check_asm_align
+          add_ldflags "-L\"${SCE_ORBIS_SDK_DIR}/target/lib/\""
+          add_ldflags "-Wl,--fself-flags=videoservice"
+          add_ldflags "-Wl,--target=orbis"
+          add_ldflags "-Wl,-lc_stub_weak"
+          add_ldflags "-Wl,-lkernel_stub_weak"
+          add_ldflags "-Wl,-lScePosix_stub_weak"
+          EXE_SFX=.elf
+          disable_feature os_support
+          soft_disable avx2
+          RTCD_OPTIONS="${RTCD_OPTIONS}--disable-avx2 "
+          ;;
+        *)
+          log "Warning: Unknown os $tgt_os while setting up $AS flags"
+          ;;
+      esac
+      ;;
+    *-gcc|generic-gnu)
+      link_with_cc=gcc
+      enable_feature gcc
+      setup_gnu_toolchain
+      ;;
+  esac
+
+  # Try to enable CPU specific tuning
+  if [ -n "${tune_cpu}" ]; then
+    if [ -n "${tune_cflags}" ]; then
+      check_add_cflags ${tune_cflags}${tune_cpu} || \
+        die "Requested CPU '${tune_cpu}' not supported by compiler"
+    fi
+    if [ -n "${tune_asflags}" ]; then
+      check_add_asflags ${tune_asflags}${tune_cpu} || \
+        die "Requested CPU '${tune_cpu}' not supported by assembler"
+    fi
+    if [ -z "${tune_cflags}${tune_asflags}" ]; then
+      log_echo "Warning: CPU tuning not supported by this toolchain"
+    fi
+  fi
+
+  if enabled debug; then
+    check_add_cflags -g && check_add_ldflags -g
+  else
+    check_add_cflags -DNDEBUG
+  fi
+
+  enabled gprof && check_add_cflags -pg && check_add_ldflags -pg
+  enabled gcov &&
+    check_add_cflags -fprofile-arcs -ftest-coverage &&
+    check_add_ldflags -fprofile-arcs -ftest-coverage
+
+  if enabled optimizations; then
+    if enabled rvct; then
+      enabled small && check_add_cflags -Ospace || check_add_cflags -Otime
+    else
+      enabled small && check_add_cflags -O2 ||  check_add_cflags -O3
+    fi
+  fi
+
+  if [ "${tgt_isa}" = "x86_64" ] || [ "${tgt_isa}" = "x86" ]; then
+    soft_enable use_x86inc
+  fi
+
+  # Position Independent Code (PIC) support, for building relocatable
+  # shared objects
+  enabled gcc && enabled pic && check_add_cflags -fPIC
+
+  # Work around longjmp interception on glibc >= 2.11, to improve binary
+  # compatibility. See http://code.google.com/p/webm/issues/detail?id=166
+  enabled linux && check_add_cflags -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
+
+  # Check for strip utility variant
+  ${STRIP} -V 2>/dev/null | grep GNU >/dev/null && enable_feature gnu_strip
+
+  # Try to determine target endianness
+  check_cc <<EOF
+unsigned int e = 'O'<<24 | '2'<<16 | 'B'<<8 | 'E';
+EOF
+    [ -f "${TMP_O}" ] && od -A n -t x1 "${TMP_O}" | tr -d '\n' |
+        grep '4f *32 *42 *45' >/dev/null 2>&1 && enable_feature big_endian
+
+    # Try to find which inline keywords are supported
+    check_cc <<EOF && INLINE="inline"
+static inline function() {}
+EOF
+
+  # Almost every platform uses pthreads.
+  if enabled multithread; then
+    case ${toolchain} in
+      *-win*-vs*)
+        ;;
+      *-android-gcc)
+        ;;
+      *orbis*)
+        ;;
+      *)
+        check_header pthread.h && add_extralibs -lpthread
+        ;;
+    esac
+  fi
+
+  # only for MIPS platforms
+  case ${toolchain} in
+    mips*)
+      if enabled big_endian; then
+        if enabled dspr2; then
+          echo "dspr2 optimizations are available only for little endian platforms"
+          disable_feature dspr2
+        fi
+        if enabled msa; then
+          echo "msa optimizations are available only for little endian platforms"
+          disable_feature msa
+        fi
+      fi
+      ;;
+  esac
+
+  # glibc needs these
+  if enabled linux; then
+    add_cflags -D_LARGEFILE_SOURCE
+    add_cflags -D_FILE_OFFSET_BITS=64
+  fi
+}
+
+process_toolchain() {
+  process_common_toolchain
+}
+
+print_config_mk() {
+  saved_prefix="${prefix}"
+  prefix=$1
+  makefile=$2
+  shift 2
+  for cfg; do
+    if enabled $cfg; then
+      upname="`toupper $cfg`"
+      echo "${prefix}_${upname}=yes" >> $makefile
+    fi
+  done
+  prefix="${saved_prefix}"
+}
+
+print_config_h() {
+  saved_prefix="${prefix}"
+  prefix=$1
+  header=$2
+  shift 2
+  for cfg; do
+    upname="`toupper $cfg`"
+    if enabled $cfg; then
+      echo "#define ${prefix}_${upname} 1" >> $header
+    else
+      echo "#define ${prefix}_${upname} 0" >> $header
+    fi
+  done
+  prefix="${saved_prefix}"
+}
+
+print_config_vars_h() {
+  header=$1
+  shift
+  while [ $# -gt 0 ]; do
+    upname="`toupper $1`"
+    echo "#define ${upname} $2" >> $header
+    shift 2
+  done
+}
+
+print_webm_license() {
+  saved_prefix="${prefix}"
+  destination=$1
+  prefix="$2"
+  suffix="$3"
+  shift 3
+  cat <<EOF > ${destination}
+${prefix} Copyright (c) 2011 The WebM project authors. All Rights Reserved.${suffix}
+${prefix} ${suffix}
+${prefix} Use of this source code is governed by a BSD-style license${suffix}
+${prefix} that can be found in the LICENSE file in the root of the source${suffix}
+${prefix} tree. An additional intellectual property rights grant can be found${suffix}
+${prefix} in the file PATENTS.  All contributing project authors may${suffix}
+${prefix} be found in the AUTHORS file in the root of the source tree.${suffix}
+EOF
+  prefix="${saved_prefix}"
+}
+
+process_targets() {
+  true;
+}
+
+process_detect() {
+  true;
+}
+
+enable_feature logging
+logfile="config.log"
+self=$0
+process() {
+  cmdline_args="$@"
+  process_cmdline "$@"
+  if enabled child; then
+    echo "# ${self} $@" >> ${logfile}
+  else
+    echo "# ${self} $@" > ${logfile}
+  fi
+  post_process_common_cmdline
+  post_process_cmdline
+  process_toolchain
+  process_detect
+  process_targets
+
+  OOT_INSTALLS="${OOT_INSTALLS}"
+  if enabled source_path_used; then
+  # Prepare the PWD for building.
+  for f in ${OOT_INSTALLS}; do
+    install -D "${source_path}/$f" "$f"
+  done
+  fi
+  cp "${source_path}/build/make/Makefile" .
+
+  clean_temp_files
+  true
+}
diff --git a/src/third_party/libvpx/build/make/gen_asm_deps.sh b/src/third_party/libvpx/build/make/gen_asm_deps.sh
new file mode 100755
index 0000000..6a7bff9
--- /dev/null
+++ b/src/third_party/libvpx/build/make/gen_asm_deps.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+self=$0
+show_help() {
+    echo "usage: $self [options] <srcfile>"
+    echo
+    echo "Generate Makefile dependency information from assembly code source"
+    echo
+    exit 1
+}
+die_unknown(){
+    echo "Unknown option \"$1\"."
+    echo "See $0 --help for available options."
+    exit 1
+}
+for opt do
+    optval="${opt#*=}"
+    case "$opt" in
+    --build-pfx=*) pfx="${optval}"
+    ;;
+    --depfile=*) out="${optval}"
+    ;;
+    -I*) raw_inc_paths="${raw_inc_paths} ${opt}"
+         inc_path="${inc_path} ${opt#-I}"
+    ;;
+    -h|--help) show_help
+    ;;
+    *) [ -f "$opt" ] && srcfile="$opt"
+    ;;
+    esac
+done
+
+[ -n "$srcfile" ] || show_help
+sfx=${sfx:-asm}
+includes=$(LC_ALL=C egrep -i "include +\"?[a-z0-9_/]+\.${sfx}" $srcfile |
+           perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;")
+#" restore editor state
+for inc in ${includes}; do
+    found_inc_path=
+    for idir in ${inc_path}; do
+        [ -f "${idir}/${inc}" ] && found_inc_path="${idir}" && break
+    done
+    if [ -f `dirname $srcfile`/$inc ]; then
+        # Handle include files in the same directory as the source
+        $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} `dirname $srcfile`/$inc
+    elif [ -n "${found_inc_path}" ]; then
+        # Handle include files on the include path
+        $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} "${found_inc_path}/$inc"
+    else
+        # Handle generated includes in the build root (which may not exist yet)
+        echo ${out} ${out%d}o: "${pfx}${inc}"
+    fi
+done
+echo ${out} ${out%d}o: $srcfile
diff --git a/src/third_party/libvpx/build/make/gen_msvs_def.sh b/src/third_party/libvpx/build/make/gen_msvs_def.sh
new file mode 100755
index 0000000..4defcc2
--- /dev/null
+++ b/src/third_party/libvpx/build/make/gen_msvs_def.sh
@@ -0,0 +1,83 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+self=$0
+self_basename=${self##*/}
+EOL=$'\n'
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} [options] file1 [file2 ...]
+
+This script generates a MSVC module definition file containing a list of symbols
+to export from a DLL. Source files are technically bash scripts (and thus may
+use #comment syntax) but in general, take the form of a list of symbols:
+
+  <kind> symbol1 [symbol2, symbol3, ...]
+
+where <kind> is either 'text' or 'data'
+
+
+Options:
+    --help                      Print this message
+    --out=filename              Write output to a file [stdout]
+    --name=project_name         Name of the library (required)
+EOF
+    exit 1
+}
+
+die() {
+    echo "${self_basename}: $@"
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"."
+    echo "See ${self_basename} --help for available options."
+    exit 1
+}
+
+text() {
+    for sym in "$@"; do
+        echo "  $sym" >> ${outfile}
+    done
+}
+
+data() {
+    for sym in "$@"; do
+        printf "  %-40s DATA\n" "$sym" >> ${outfile}
+    done
+}
+
+# Process command line
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --help|-h) show_help
+    ;;
+    --out=*) outfile="$optval"
+    ;;
+    --name=*) name="${optval}"
+    ;;
+     -*) die_unknown $opt
+    ;;
+    *) file_list[${#file_list[@]}]="$opt"
+    esac
+done
+outfile=${outfile:-/dev/stdout}
+[ -n "$name" ] || die "Library name (--name) must be specified!"
+
+echo "LIBRARY ${name}" > ${outfile}
+echo "EXPORTS" >> ${outfile}
+for f in "${file_list[@]}"; do
+    . $f
+done
diff --git a/src/third_party/libvpx/build/make/gen_msvs_proj.sh b/src/third_party/libvpx/build/make/gen_msvs_proj.sh
new file mode 100755
index 0000000..2b91fbf
--- /dev/null
+++ b/src/third_party/libvpx/build/make/gen_msvs_proj.sh
@@ -0,0 +1,490 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+self=$0
+self_basename=${self##*/}
+self_dirname=$(dirname "$0")
+
+. "$self_dirname/msvs_common.sh"|| exit 127
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
+
+This script generates a Visual Studio project file from a list of source
+code files.
+
+Options:
+    --help                      Print this message
+    --exe                       Generate a project for building an Application
+    --lib                       Generate a project for creating a static library
+    --dll                       Generate a project for creating a dll
+    --static-crt                Use the static C runtime (/MT)
+    --target=isa-os-cc          Target specifier (required)
+    --out=filename              Write output to a file [stdout]
+    --name=project_name         Name of the project (required)
+    --proj-guid=GUID            GUID to use for the project
+    --module-def=filename       File containing export definitions (for DLLs)
+    --ver=version               Version (7,8,9) of visual studio to generate for
+    --src-path-bare=dir         Path to root of source tree
+    -Ipath/to/include           Additional include directories
+    -DFLAG[=value]              Preprocessor macros to define
+    -Lpath/to/lib               Additional library search paths
+    -llibname                   Library to link against
+EOF
+    exit 1
+}
+
+generate_filter() {
+    local var=$1
+    local name=$2
+    local pats=$3
+    local file_list_sz
+    local i
+    local f
+    local saveIFS="$IFS"
+    local pack
+    echo "generating filter '$name' from ${#file_list[@]} files" >&2
+    IFS=*
+
+    open_tag Filter \
+        Name=$name \
+        Filter=$pats \
+        UniqueIdentifier=`generate_uuid` \
+
+    file_list_sz=${#file_list[@]}
+    for i in ${!file_list[@]}; do
+        f=${file_list[i]}
+        for pat in ${pats//;/$IFS}; do
+            if [ "${f##*.}" == "$pat" ]; then
+                unset file_list[i]
+
+                objf=$(echo ${f%.*}.obj \
+                       | sed -e "s,$src_path_bare,," \
+                             -e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
+                open_tag File RelativePath="$f"
+
+                if [ "$pat" == "asm" ] && $asm_use_custom_step; then
+                    # Avoid object file name collisions, i.e. vpx_config.c and
+                    # vpx_config.asm produce the same object file without
+                    # this additional suffix.
+                    objf=${objf%.obj}_asm.obj
+                    for plat in "${platforms[@]}"; do
+                        for cfg in Debug Release; do
+                            open_tag FileConfiguration \
+                                Name="${cfg}|${plat}" \
+
+                            tag Tool \
+                                Name="VCCustomBuildTool" \
+                                Description="Assembling \$(InputFileName)" \
+                                CommandLine="$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)\\$objf" \
+                                Outputs="\$(IntDir)\\$objf" \
+
+                            close_tag FileConfiguration
+                        done
+                    done
+                fi
+                if [ "$pat" == "c" ] || \
+                   [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
+                    for plat in "${platforms[@]}"; do
+                        for cfg in Debug Release; do
+                            open_tag FileConfiguration \
+                                Name="${cfg}|${plat}" \
+
+                            tag Tool \
+                                Name="VCCLCompilerTool" \
+                                ObjectFile="\$(IntDir)\\$objf" \
+
+                            close_tag FileConfiguration
+                        done
+                    done
+                fi
+                close_tag File
+
+                break
+            fi
+        done
+    done
+
+    close_tag Filter
+    IFS="$saveIFS"
+}
+
+# Process command line
+unset target
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+        --help|-h) show_help
+        ;;
+        --target=*) target="${optval}"
+        ;;
+        --out=*) outfile="$optval"
+        ;;
+        --name=*) name="${optval}"
+        ;;
+        --proj-guid=*) guid="${optval}"
+        ;;
+        --module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}"
+        ;;
+        --exe) proj_kind="exe"
+        ;;
+        --dll) proj_kind="dll"
+        ;;
+        --lib) proj_kind="lib"
+        ;;
+        --src-path-bare=*)
+            src_path_bare=$(fix_path "$optval")
+            src_path_bare=${src_path_bare%/}
+        ;;
+        --static-crt) use_static_runtime=true
+        ;;
+        --ver=*)
+            vs_ver="$optval"
+            case "$optval" in
+                [789])
+                ;;
+                *) die Unrecognized Visual Studio Version in $opt
+                ;;
+            esac
+        ;;
+        -I*)
+            opt=${opt##-I}
+            opt=$(fix_path "$opt")
+            opt="${opt%/}"
+            incs="${incs}${incs:+;}&quot;${opt}&quot;"
+            yasmincs="${yasmincs} -I&quot;${opt}&quot;"
+        ;;
+        -D*) defines="${defines}${defines:+;}${opt##-D}"
+        ;;
+        -L*) # fudge . to $(OutDir)
+            if [ "${opt##-L}" == "." ]; then
+                libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
+            else
+                 # Also try directories for this platform/configuration
+                 opt=${opt##-L}
+                 opt=$(fix_path "$opt")
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)/\$(ConfigurationName)&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)&quot;"
+            fi
+        ;;
+        -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
+        ;;
+        -*) die_unknown $opt
+        ;;
+        *)
+            # The paths in file_list are fixed outside of the loop.
+            file_list[${#file_list[@]}]="$opt"
+            case "$opt" in
+                 *.asm) uses_asm=true
+                 ;;
+            esac
+        ;;
+    esac
+done
+
+# Make one call to fix_path for file_list to improve performance.
+fix_file_list file_list
+
+outfile=${outfile:-/dev/stdout}
+guid=${guid:-`generate_uuid`}
+asm_use_custom_step=false
+uses_asm=${uses_asm:-false}
+case "${vs_ver:-8}" in
+    7) vs_ver_id="7.10"
+       asm_use_custom_step=$uses_asm
+       warn_64bit='Detect64BitPortabilityProblems=true'
+    ;;
+    8) vs_ver_id="8.00"
+       asm_use_custom_step=$uses_asm
+       warn_64bit='Detect64BitPortabilityProblems=true'
+    ;;
+    9) vs_ver_id="9.00"
+       asm_use_custom_step=$uses_asm
+       warn_64bit='Detect64BitPortabilityProblems=false'
+    ;;
+esac
+
+[ -n "$name" ] || die "Project name (--name) must be specified!"
+[ -n "$target" ] || die "Target (--target) must be specified!"
+
+if ${use_static_runtime:-false}; then
+    release_runtime=0
+    debug_runtime=1
+    lib_sfx=mt
+else
+    release_runtime=2
+    debug_runtime=3
+    lib_sfx=md
+fi
+
+# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
+# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
+# debug exe, so this may need to be refactored later.
+for lib in ${libs}; do
+    if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
+        lib=${lib%.lib}d.lib
+    fi
+    debug_libs="${debug_libs}${debug_libs:+ }${lib}"
+done
+
+
+# List Keyword for this target
+case "$target" in
+    x86*) keyword="ManagedCProj"
+    ;;
+    *) die "Unsupported target $target!"
+esac
+
+# List of all platforms supported for this target
+case "$target" in
+    x86_64*)
+        platforms[0]="x64"
+        asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} &quot;\$(InputPath)&quot;"
+        asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} &quot;\$(InputPath)&quot;"
+    ;;
+    x86*)
+        platforms[0]="Win32"
+        asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} &quot;\$(InputPath)&quot;"
+        asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} &quot;\$(InputPath)&quot;"
+    ;;
+    *) die "Unsupported target $target!"
+    ;;
+esac
+
+generate_vcproj() {
+    case "$proj_kind" in
+        exe) vs_ConfigurationType=1
+        ;;
+        dll) vs_ConfigurationType=2
+        ;;
+        *)   vs_ConfigurationType=4
+        ;;
+    esac
+
+    echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
+    open_tag VisualStudioProject \
+        ProjectType="Visual C++" \
+        Version="${vs_ver_id}" \
+        Name="${name}" \
+        ProjectGUID="{${guid}}" \
+        RootNamespace="${name}" \
+        Keyword="${keyword}" \
+
+    open_tag Platforms
+    for plat in "${platforms[@]}"; do
+        tag Platform Name="$plat"
+    done
+    close_tag Platforms
+
+    open_tag Configurations
+    for plat in "${platforms[@]}"; do
+        plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
+        open_tag Configuration \
+            Name="Debug|$plat" \
+            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
+            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
+            ConfigurationType="$vs_ConfigurationType" \
+            CharacterSet="1" \
+
+        case "$target" in
+            x86*)
+                case "$name" in
+                    vpx)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="0" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$debug_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="2" \
+                            $warn_64bit \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
+                    ;;
+                    *)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="0" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$debug_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="2" \
+                            $warn_64bit \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs" Debug="true"
+                    ;;
+                esac
+            ;;
+        esac
+
+        case "$proj_kind" in
+            exe)
+                case "$target" in
+                    x86*)
+                        case "$name" in
+                            *)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    AdditionalDependencies="$debug_libs \$(NoInherit)" \
+                                    AdditionalLibraryDirectories="$libdirs" \
+                                    GenerateDebugInformation="true" \
+                                    ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
+                            ;;
+                        esac
+                    ;;
+                 esac
+            ;;
+            lib)
+                case "$target" in
+                    x86*)
+                        tag Tool \
+                            Name="VCLibrarianTool" \
+                            OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
+
+                    ;;
+                esac
+            ;;
+            dll)
+                tag Tool \
+                    Name="VCLinkerTool" \
+                    AdditionalDependencies="\$(NoInherit)" \
+                    LinkIncremental="2" \
+                    GenerateDebugInformation="true" \
+                    AssemblyDebug="1" \
+                    TargetMachine="1" \
+                    $link_opts \
+
+            ;;
+        esac
+
+        close_tag Configuration
+
+        open_tag Configuration \
+            Name="Release|$plat" \
+            OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
+            IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
+            ConfigurationType="$vs_ConfigurationType" \
+            CharacterSet="1" \
+            WholeProgramOptimization="0" \
+
+        case "$target" in
+            x86*)
+                case "$name" in
+                    vpx)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            Optimization="2" \
+                            FavorSizeorSpeed="1" \
+                            AdditionalIncludeDirectories="$incs" \
+                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$release_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="0" \
+                            $warn_64bit \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
+                    ;;
+                    *)
+                        tag Tool \
+                            Name="VCCLCompilerTool" \
+                            AdditionalIncludeDirectories="$incs" \
+                            Optimization="2" \
+                            FavorSizeorSpeed="1" \
+                            PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
+                            RuntimeLibrary="$release_runtime" \
+                            UsePrecompiledHeader="0" \
+                            WarningLevel="3" \
+                            DebugInformationFormat="0" \
+                            $warn_64bit \
+
+                        $uses_asm && tag Tool Name="YASM"  IncludePaths="$incs"
+                    ;;
+                esac
+            ;;
+        esac
+
+        case "$proj_kind" in
+            exe)
+                case "$target" in
+                    x86*)
+                        case "$name" in
+                            *)
+                                tag Tool \
+                                    Name="VCLinkerTool" \
+                                    AdditionalDependencies="$libs \$(NoInherit)" \
+                                    AdditionalLibraryDirectories="$libdirs" \
+
+                            ;;
+                        esac
+                    ;;
+                 esac
+            ;;
+            lib)
+                case "$target" in
+                    x86*)
+                        tag Tool \
+                            Name="VCLibrarianTool" \
+                            OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
+
+                    ;;
+                esac
+            ;;
+            dll) # note differences to debug version: LinkIncremental, AssemblyDebug
+                tag Tool \
+                    Name="VCLinkerTool" \
+                    AdditionalDependencies="\$(NoInherit)" \
+                    LinkIncremental="1" \
+                    GenerateDebugInformation="true" \
+                    TargetMachine="1" \
+                    $link_opts \
+
+            ;;
+        esac
+
+        close_tag Configuration
+    done
+    close_tag Configurations
+
+    open_tag Files
+    generate_filter srcs   "Source Files"   "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx"
+    generate_filter hdrs   "Header Files"   "h;hm;inl;inc;xsd"
+    generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+    generate_filter resrcs "Build Files"    "mk"
+    close_tag Files
+
+    tag       Globals
+    close_tag VisualStudioProject
+
+    # This must be done from within the {} subshell
+    echo "Ignored files list (${#file_list[@]} items) is:" >&2
+    for f in "${file_list[@]}"; do
+        echo "    $f" >&2
+    done
+}
+
+generate_vcproj |
+    sed  -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
+
+exit
+<!--
+TODO: Add any files not captured by filters.
+                <File
+                        RelativePath=".\ReadMe.txt"
+                        >
+                </File>
+-->
diff --git a/src/third_party/libvpx/build/make/gen_msvs_sln.sh b/src/third_party/libvpx/build/make/gen_msvs_sln.sh
new file mode 100755
index 0000000..664b404
--- /dev/null
+++ b/src/third_party/libvpx/build/make/gen_msvs_sln.sh
@@ -0,0 +1,327 @@
+#!/bin/bash
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+self=$0
+self_basename=${self##*/}
+EOL=$'\n'
+EOLDOS=$'\r'
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} [options] file1 [file2 ...]
+
+This script generates a Visual Studio solution file from a list of project
+files.
+
+Options:
+    --help                      Print this message
+    --out=outfile               Redirect output to a file
+    --ver=version               Version (7,8,9,10,11,12,14) of visual studio to generate for
+    --target=isa-os-cc          Target specifier
+EOF
+    exit 1
+}
+
+die() {
+    echo "${self_basename}: $@" >&2
+    [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"." >&2
+    echo "See ${self_basename} --help for available options." >&2
+    [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
+    exit 1
+}
+
+indent1=$'\t'
+indent=""
+indent_push() {
+    indent="${indent}${indent1}"
+}
+indent_pop() {
+    indent="${indent%${indent1}}"
+}
+
+parse_project() {
+    local file=$1
+    if [ "$sfx" = "vcproj" ]; then
+        local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
+        local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
+    else
+        local name=`grep RootNamespace "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
+        local guid=`grep ProjectGuid "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
+    fi
+
+    # save the project GUID to a varaible, normalizing to the basename of the
+    # vcproj file without the extension
+    local var
+    var=${file##*/}
+    var=${var%%.${sfx}}
+    eval "${var}_file=\"$1\""
+    eval "${var}_name=$name"
+    eval "${var}_guid=$guid"
+
+    if [ "$sfx" = "vcproj" ]; then
+        cur_config_list=`grep -A1 '<Configuration' $file |
+            grep Name | cut -d\" -f2`
+    else
+        cur_config_list=`grep -B1 'Label="Configuration"' $file |
+            grep Condition | cut -d\' -f4`
+    fi
+    new_config_list=$(for i in $config_list $cur_config_list; do
+        echo $i
+    done | sort | uniq)
+    if [ "$config_list" != "" ] && [ "$config_list" != "$new_config_list" ]; then
+        mixed_platforms=1
+    fi
+    config_list="$new_config_list"
+    eval "${var}_config_list=\"$cur_config_list\""
+    proj_list="${proj_list} ${var}"
+}
+
+process_project() {
+    eval "local file=\${$1_file}"
+    eval "local name=\${$1_name}"
+    eval "local guid=\${$1_guid}"
+
+    # save the project GUID to a varaible, normalizing to the basename of the
+    # vcproj file without the extension
+    local var
+    var=${file##*/}
+    var=${var%%.${sfx}}
+    eval "${var}_guid=$guid"
+
+    echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\""
+    indent_push
+
+    eval "local deps=\"\${${var}_deps}\""
+    if [ -n "$deps" ] && [ "$sfx" = "vcproj" ]; then
+        echo "${indent}ProjectSection(ProjectDependencies) = postProject"
+        indent_push
+
+        for dep in $deps; do
+            eval "local dep_guid=\${${dep}_guid}"
+            [ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)"
+            echo "${indent}$dep_guid = $dep_guid"
+        done
+
+        indent_pop
+        echo "${indent}EndProjectSection"
+
+    fi
+
+    indent_pop
+    echo "EndProject"
+}
+
+process_global() {
+    echo "Global"
+    indent_push
+
+    #
+    # Solution Configuration Platforms
+    #
+    echo "${indent}GlobalSection(SolutionConfigurationPlatforms) = preSolution"
+    indent_push
+    IFS_bak=${IFS}
+    IFS=$'\r'$'\n'
+    if [ "$mixed_platforms" != "" ]; then
+        config_list="
+Release|Mixed Platforms
+Debug|Mixed Platforms"
+    fi
+    for config in ${config_list}; do
+        echo "${indent}$config = $config"
+    done
+    IFS=${IFS_bak}
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    #
+    # Project Configuration Platforms
+    #
+    echo "${indent}GlobalSection(ProjectConfigurationPlatforms) = postSolution"
+    indent_push
+    for proj in ${proj_list}; do
+        eval "local proj_guid=\${${proj}_guid}"
+        eval "local proj_config_list=\${${proj}_config_list}"
+        IFS=$'\r'$'\n'
+        for config in ${proj_config_list}; do
+            if [ "$mixed_platforms" != "" ]; then
+                local c=${config%%|*}
+                echo "${indent}${proj_guid}.${c}|Mixed Platforms.ActiveCfg = ${config}"
+                echo "${indent}${proj_guid}.${c}|Mixed Platforms.Build.0 = ${config}"
+            else
+                echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}"
+                echo "${indent}${proj_guid}.${config}.Build.0 = ${config}"
+            fi
+
+        done
+        IFS=${IFS_bak}
+    done
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    #
+    # Solution Properties
+    #
+    echo "${indent}GlobalSection(SolutionProperties) = preSolution"
+    indent_push
+    echo "${indent}HideSolutionNode = FALSE"
+    indent_pop
+    echo "${indent}EndGlobalSection"
+
+    indent_pop
+    echo "EndGlobal"
+}
+
+process_makefile() {
+    IFS_bak=${IFS}
+    IFS=$'\r'$'\n'
+    local TAB=$'\t'
+    cat <<EOF
+ifeq (\$(CONFIG_VS_VERSION),7)
+MSBUILD_TOOL := devenv.com
+else
+MSBUILD_TOOL := msbuild.exe
+endif
+found_devenv := \$(shell which \$(MSBUILD_TOOL) >/dev/null 2>&1 && echo yes)
+.nodevenv.once:
+${TAB}@echo "  * \$(MSBUILD_TOOL) not found in path."
+${TAB}@echo "  * "
+${TAB}@echo "  * You will have to build all configurations manually using the"
+${TAB}@echo "  * Visual Studio IDE. To allow make to build them automatically,"
+${TAB}@echo "  * add the Common7/IDE directory of your Visual Studio"
+${TAB}@echo "  * installation to your path, eg:"
+${TAB}@echo "  *   C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"
+${TAB}@echo "  * "
+${TAB}@touch \$@
+CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
+
+EOF
+
+    for sln_config in ${config_list}; do
+        local config=${sln_config%%|*}
+        local platform=${sln_config##*|}
+        local nows_sln_config=`echo $sln_config | sed -e 's/[^a-zA-Z0-9]/_/g'`
+        cat <<EOF
+BUILD_TARGETS += \$(if \$(NO_LAUNCH_DEVENV),,$nows_sln_config)
+clean::
+${TAB}rm -rf "$platform"/"$config"
+.PHONY: $nows_sln_config
+ifneq (\$(found_devenv),)
+  ifeq (\$(CONFIG_VS_VERSION),7)
+$nows_sln_config: $outfile
+${TAB}\$(MSBUILD_TOOL) $outfile -build "$config"
+
+  else
+$nows_sln_config: $outfile
+${TAB}\$(MSBUILD_TOOL) $outfile -m -t:Build \\
+${TAB}${TAB}-p:Configuration="$config" -p:Platform="$platform"
+
+  endif
+else
+$nows_sln_config: $outfile .nodevenv.once
+${TAB}@echo "  * Skipping build of $sln_config (\$(MSBUILD_TOOL) not in path)."
+${TAB}@echo "  * "
+endif
+
+EOF
+    done
+    IFS=${IFS_bak}
+}
+
+# Process command line
+outfile=/dev/stdout
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --help|-h) show_help
+    ;;
+    --out=*) outfile="${optval}"; mkoutfile="${optval}".mk
+    ;;
+    --dep=*) eval "${optval%%:*}_deps=\"\${${optval%%:*}_deps} ${optval##*:}\""
+    ;;
+    --ver=*) vs_ver="$optval"
+             case $optval in
+             [789]|10|11|12|14)
+             ;;
+             *) die Unrecognized Visual Studio Version in $opt
+             ;;
+             esac
+    ;;
+    --ver=*) vs_ver="$optval"
+             case $optval in
+             7) sln_vers="8.00"
+                sln_vers_str="Visual Studio .NET 2003"
+             ;;
+             [89])
+             ;;
+             *) die "Unrecognized Visual Studio Version '$optval' in $opt"
+             ;;
+             esac
+    ;;
+    --target=*) target="${optval}"
+    ;;
+    -*) die_unknown $opt
+    ;;
+    *) file_list[${#file_list[@]}]="$opt"
+    esac
+done
+outfile=${outfile:-/dev/stdout}
+mkoutfile=${mkoutfile:-/dev/stdout}
+case "${vs_ver:-8}" in
+    7) sln_vers="8.00"
+       sln_vers_str="Visual Studio .NET 2003"
+    ;;
+    8) sln_vers="9.00"
+       sln_vers_str="Visual Studio 2005"
+    ;;
+    9) sln_vers="10.00"
+       sln_vers_str="Visual Studio 2008"
+    ;;
+    10) sln_vers="11.00"
+       sln_vers_str="Visual Studio 2010"
+    ;;
+    11) sln_vers="12.00"
+       sln_vers_str="Visual Studio 2012"
+    ;;
+    12) sln_vers="12.00"
+       sln_vers_str="Visual Studio 2013"
+    ;;
+    14) sln_vers="14.00"
+       sln_vers_str="Visual Studio 2015"
+    ;;
+esac
+case "${vs_ver:-8}" in
+    [789])
+    sfx=vcproj
+    ;;
+    10|11|12|14)
+    sfx=vcxproj
+    ;;
+esac
+
+for f in "${file_list[@]}"; do
+    parse_project $f
+done
+cat  >${outfile} <<EOF
+Microsoft Visual Studio Solution File, Format Version $sln_vers${EOLDOS}
+# $sln_vers_str${EOLDOS}
+EOF
+for proj in ${proj_list}; do
+    process_project $proj >>${outfile}
+done
+process_global >>${outfile}
+process_makefile >${mkoutfile}
diff --git a/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh b/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh
new file mode 100755
index 0000000..e98611d
--- /dev/null
+++ b/src/third_party/libvpx/build/make/gen_msvs_vcxproj.sh
@@ -0,0 +1,490 @@
+#!/bin/bash
+##
+##  Copyright (c) 2013 The WebM 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.
+##
+
+self=$0
+self_basename=${self##*/}
+self_dirname=$(dirname "$0")
+
+. "$self_dirname/msvs_common.sh"|| exit 127
+
+show_help() {
+    cat <<EOF
+Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
+
+This script generates a Visual Studio project file from a list of source
+code files.
+
+Options:
+    --help                      Print this message
+    --exe                       Generate a project for building an Application
+    --lib                       Generate a project for creating a static library
+    --dll                       Generate a project for creating a dll
+    --static-crt                Use the static C runtime (/MT)
+    --enable-werror             Treat warnings as errors (/WX)
+    --target=isa-os-cc          Target specifier (required)
+    --out=filename              Write output to a file [stdout]
+    --name=project_name         Name of the project (required)
+    --proj-guid=GUID            GUID to use for the project
+    --module-def=filename       File containing export definitions (for DLLs)
+    --ver=version               Version (10,11,12,14) of visual studio to generate for
+    --src-path-bare=dir         Path to root of source tree
+    -Ipath/to/include           Additional include directories
+    -DFLAG[=value]              Preprocessor macros to define
+    -Lpath/to/lib               Additional library search paths
+    -llibname                   Library to link against
+EOF
+    exit 1
+}
+
+tag_content() {
+    local tag=$1
+    local content=$2
+    shift
+    shift
+    if [ $# -ne 0 ]; then
+        echo "${indent}<${tag}"
+        indent_push
+        tag_attributes "$@"
+        echo "${indent}>${content}</${tag}>"
+        indent_pop
+    else
+        echo "${indent}<${tag}>${content}</${tag}>"
+    fi
+}
+
+generate_filter() {
+    local name=$1
+    local pats=$2
+    local file_list_sz
+    local i
+    local f
+    local saveIFS="$IFS"
+    local pack
+    echo "generating filter '$name' from ${#file_list[@]} files" >&2
+    IFS=*
+
+    file_list_sz=${#file_list[@]}
+    for i in ${!file_list[@]}; do
+        f=${file_list[i]}
+        for pat in ${pats//;/$IFS}; do
+            if [ "${f##*.}" == "$pat" ]; then
+                unset file_list[i]
+
+                objf=$(echo ${f%.*}.obj \
+                       | sed -e "s,$src_path_bare,," \
+                             -e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
+
+                if ([ "$pat" == "asm" ] || [ "$pat" == "s" ]) && $asm_use_custom_step; then
+                    # Avoid object file name collisions, i.e. vpx_config.c and
+                    # vpx_config.asm produce the same object file without
+                    # this additional suffix.
+                    objf=${objf%.obj}_asm.obj
+                    open_tag CustomBuild \
+                        Include="$f"
+                    for plat in "${platforms[@]}"; do
+                        for cfg in Debug Release; do
+                            tag_content Message "Assembling %(Filename)%(Extension)" \
+                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
+                            tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \
+                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
+                            tag_content Outputs "\$(IntDir)$objf" \
+                                Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
+                        done
+                    done
+                    close_tag CustomBuild
+                elif [ "$pat" == "c" ] || \
+                     [ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
+                    open_tag ClCompile \
+                        Include="$f"
+                    # Separate file names with Condition?
+                    tag_content ObjectFileName "\$(IntDir)$objf"
+                    # Check for AVX and turn it on to avoid warnings.
+                    if [[ $f =~ avx.?\.c$ ]]; then
+                        tag_content AdditionalOptions "/arch:AVX"
+                    fi
+                    close_tag ClCompile
+                elif [ "$pat" == "h" ] ; then
+                    tag ClInclude \
+                        Include="$f"
+                elif [ "$pat" == "vcxproj" ] ; then
+                    open_tag ProjectReference \
+                        Include="$f"
+                    depguid=`grep ProjectGuid "$f" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
+                    tag_content Project "$depguid"
+                    tag_content ReferenceOutputAssembly false
+                    close_tag ProjectReference
+                else
+                    tag None \
+                        Include="$f"
+                fi
+
+                break
+            fi
+        done
+    done
+
+    IFS="$saveIFS"
+}
+
+# Process command line
+unset target
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+        --help|-h) show_help
+        ;;
+        --target=*) target="${optval}"
+        ;;
+        --out=*) outfile="$optval"
+        ;;
+        --name=*) name="${optval}"
+        ;;
+        --proj-guid=*) guid="${optval}"
+        ;;
+        --module-def=*) module_def="${optval}"
+        ;;
+        --exe) proj_kind="exe"
+        ;;
+        --dll) proj_kind="dll"
+        ;;
+        --lib) proj_kind="lib"
+        ;;
+        --src-path-bare=*)
+            src_path_bare=$(fix_path "$optval")
+            src_path_bare=${src_path_bare%/}
+        ;;
+        --static-crt) use_static_runtime=true
+        ;;
+        --enable-werror) werror=true
+        ;;
+        --ver=*)
+            vs_ver="$optval"
+            case "$optval" in
+                10|11|12|14)
+                ;;
+                *) die Unrecognized Visual Studio Version in $opt
+                ;;
+            esac
+        ;;
+        -I*)
+            opt=${opt##-I}
+            opt=$(fix_path "$opt")
+            opt="${opt%/}"
+            incs="${incs}${incs:+;}&quot;${opt}&quot;"
+            yasmincs="${yasmincs} -I&quot;${opt}&quot;"
+        ;;
+        -D*) defines="${defines}${defines:+;}${opt##-D}"
+        ;;
+        -L*) # fudge . to $(OutDir)
+            if [ "${opt##-L}" == "." ]; then
+                libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
+            else
+                 # Also try directories for this platform/configuration
+                 opt=${opt##-L}
+                 opt=$(fix_path "$opt")
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)/\$(Configuration)&quot;"
+                 libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)&quot;"
+            fi
+        ;;
+        -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
+        ;;
+        -*) die_unknown $opt
+        ;;
+        *)
+            # The paths in file_list are fixed outside of the loop.
+            file_list[${#file_list[@]}]="$opt"
+            case "$opt" in
+                 *.asm|*.s) uses_asm=true
+                 ;;
+            esac
+        ;;
+    esac
+done
+
+# Make one call to fix_path for file_list to improve performance.
+fix_file_list file_list
+
+outfile=${outfile:-/dev/stdout}
+guid=${guid:-`generate_uuid`}
+asm_use_custom_step=false
+uses_asm=${uses_asm:-false}
+case "${vs_ver:-11}" in
+    10|11|12|14)
+       asm_use_custom_step=$uses_asm
+    ;;
+esac
+
+[ -n "$name" ] || die "Project name (--name) must be specified!"
+[ -n "$target" ] || die "Target (--target) must be specified!"
+
+if ${use_static_runtime:-false}; then
+    release_runtime=MultiThreaded
+    debug_runtime=MultiThreadedDebug
+    lib_sfx=mt
+else
+    release_runtime=MultiThreadedDLL
+    debug_runtime=MultiThreadedDebugDLL
+    lib_sfx=md
+fi
+
+# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
+# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
+# debug exe, so this may need to be refactored later.
+for lib in ${libs}; do
+    if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
+        lib=${lib%.lib}d.lib
+    fi
+    debug_libs="${debug_libs}${debug_libs:+ }${lib}"
+done
+debug_libs=${debug_libs// /;}
+libs=${libs// /;}
+
+
+# List of all platforms supported for this target
+case "$target" in
+    x86_64*)
+        platforms[0]="x64"
+        asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
+        asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
+    ;;
+    x86*)
+        platforms[0]="Win32"
+        asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
+        asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
+    ;;
+    arm*)
+        platforms[0]="ARM"
+        asm_Debug_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
+        asm_Release_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
+    ;;
+    *) die "Unsupported target $target!"
+    ;;
+esac
+
+generate_vcxproj() {
+    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
+    open_tag Project \
+        DefaultTargets="Build" \
+        ToolsVersion="4.0" \
+        xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \
+
+    open_tag ItemGroup \
+        Label="ProjectConfigurations"
+    for plat in "${platforms[@]}"; do
+        for config in Debug Release; do
+            open_tag ProjectConfiguration \
+                Include="$config|$plat"
+            tag_content Configuration $config
+            tag_content Platform $plat
+            close_tag ProjectConfiguration
+        done
+    done
+    close_tag ItemGroup
+
+    open_tag PropertyGroup \
+        Label="Globals"
+        tag_content ProjectGuid "{${guid}}"
+        tag_content RootNamespace ${name}
+        tag_content Keyword ManagedCProj
+        if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
+            tag_content AppContainerApplication true
+            # The application type can be one of "Windows Store",
+            # "Windows Phone" or "Windows Phone Silverlight". The
+            # actual value doesn't matter from the libvpx point of view,
+            # since a static library built for one works on the others.
+            # The PlatformToolset field needs to be set in sync with this;
+            # for Windows Store and Windows Phone Silverlight it should be
+            # v120 while it should be v120_wp81 if the type is Windows Phone.
+            tag_content ApplicationType "Windows Store"
+            tag_content ApplicationTypeRevision 8.1
+        fi
+    close_tag PropertyGroup
+
+    tag Import \
+        Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
+
+    for plat in "${platforms[@]}"; do
+        for config in Release Debug; do
+            open_tag PropertyGroup \
+                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \
+                Label="Configuration"
+            if [ "$proj_kind" = "exe" ]; then
+                tag_content ConfigurationType Application
+            elif [ "$proj_kind" = "dll" ]; then
+                tag_content ConfigurationType DynamicLibrary
+            else
+                tag_content ConfigurationType StaticLibrary
+            fi
+            if [ "$vs_ver" = "11" ]; then
+                if [ "$plat" = "ARM" ]; then
+                    # Setting the wp80 toolchain automatically sets the
+                    # WINAPI_FAMILY define, which is required for building
+                    # code for arm with the windows headers. Alternatively,
+                    # one could add AppContainerApplication=true in the Globals
+                    # section and add PrecompiledHeader=NotUsing and
+                    # CompileAsWinRT=false in ClCompile and SubSystem=Console
+                    # in Link.
+                    tag_content PlatformToolset v110_wp80
+                else
+                    tag_content PlatformToolset v110
+                fi
+            fi
+            if [ "$vs_ver" = "12" ]; then
+                # Setting a PlatformToolset indicating windows phone isn't
+                # enough to build code for arm with MSVC 2013, one strictly
+                # has to enable AppContainerApplication as well.
+                tag_content PlatformToolset v120
+            fi
+            if [ "$vs_ver" = "14" ]; then
+                tag_content PlatformToolset v140
+            fi
+            tag_content CharacterSet Unicode
+            if [ "$config" = "Release" ]; then
+                tag_content WholeProgramOptimization true
+            fi
+            close_tag PropertyGroup
+        done
+    done
+
+    tag Import \
+        Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
+
+    open_tag ImportGroup \
+        Label="PropertySheets"
+        tag Import \
+            Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
+            Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
+            Label="LocalAppDataPlatform"
+    close_tag ImportGroup
+
+    tag PropertyGroup \
+        Label="UserMacros"
+
+    for plat in "${platforms[@]}"; do
+        plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
+        for config in Debug Release; do
+            open_tag PropertyGroup \
+                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
+            tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
+            tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
+            if [ "$proj_kind" == "lib" ]; then
+              if [ "$config" == "Debug" ]; then
+                config_suffix=d
+              else
+                config_suffix=""
+              fi
+              tag_content TargetName "${name}${lib_sfx}${config_suffix}"
+            fi
+            close_tag PropertyGroup
+        done
+    done
+
+    for plat in "${platforms[@]}"; do
+        for config in Debug Release; do
+            open_tag ItemDefinitionGroup \
+                Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
+            if [ "$name" == "vpx" ]; then
+                hostplat=$plat
+                if [ "$hostplat" == "ARM" ]; then
+                    hostplat=Win32
+                fi
+            fi
+            open_tag ClCompile
+            if [ "$config" = "Debug" ]; then
+                opt=Disabled
+                runtime=$debug_runtime
+                curlibs=$debug_libs
+                debug=_DEBUG
+            else
+                opt=MaxSpeed
+                runtime=$release_runtime
+                curlibs=$libs
+                tag_content FavorSizeOrSpeed Speed
+                debug=NDEBUG
+            fi
+            extradefines=";$defines"
+            tag_content Optimization $opt
+            tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
+            tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
+            tag_content RuntimeLibrary $runtime
+            tag_content WarningLevel Level3
+            if ${werror:-false}; then
+                tag_content TreatWarningAsError true
+            fi
+            if [ $vs_ver -ge 11 ]; then
+                # We need to override the defaults for these settings
+                # if AppContainerApplication is set.
+                tag_content CompileAsWinRT false
+                tag_content PrecompiledHeader NotUsing
+                tag_content SDLCheck false
+            fi
+            close_tag ClCompile
+            case "$proj_kind" in
+            exe)
+                open_tag Link
+                tag_content GenerateDebugInformation true
+                # Console is the default normally, but if
+                # AppContainerApplication is set, we need to override it.
+                tag_content SubSystem Console
+                close_tag Link
+                ;;
+            dll)
+                open_tag Link
+                tag_content GenerateDebugInformation true
+                tag_content ModuleDefinitionFile $module_def
+                close_tag Link
+                ;;
+            lib)
+                ;;
+            esac
+            close_tag ItemDefinitionGroup
+        done
+
+    done
+
+    open_tag ItemGroup
+    generate_filter "Source Files"   "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s"
+    close_tag ItemGroup
+    open_tag ItemGroup
+    generate_filter "Header Files"   "h;hm;inl;inc;xsd"
+    close_tag ItemGroup
+    open_tag ItemGroup
+    generate_filter "Build Files"    "mk"
+    close_tag ItemGroup
+    open_tag ItemGroup
+    generate_filter "References"     "vcxproj"
+    close_tag ItemGroup
+
+    tag Import \
+        Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
+
+    open_tag ImportGroup \
+        Label="ExtensionTargets"
+    close_tag ImportGroup
+
+    close_tag Project
+
+    # This must be done from within the {} subshell
+    echo "Ignored files list (${#file_list[@]} items) is:" >&2
+    for f in "${file_list[@]}"; do
+        echo "    $f" >&2
+    done
+}
+
+# This regexp doesn't catch most of the strings in the vcxproj format,
+# since they're like <tag>path</tag> instead of <tag attr="path" />
+# as previously. It still seems to work ok despite this.
+generate_vcxproj |
+    sed  -e '/"/s;\([^ "]\)/;\1\\;g' |
+    sed  -e '/xmlns/s;\\;/;g' > ${outfile}
+
+exit
diff --git a/src/third_party/libvpx/build/make/ios-Info.plist b/src/third_party/libvpx/build/make/ios-Info.plist
new file mode 100644
index 0000000..d157b11
--- /dev/null
+++ b/src/third_party/libvpx/build/make/ios-Info.plist
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleDevelopmentRegion</key>
+	<string>en</string>
+	<key>CFBundleExecutable</key>
+	<string>VPX</string>
+	<key>CFBundleIdentifier</key>
+	<string>org.webmproject.VPX</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>VPX</string>
+	<key>CFBundlePackageType</key>
+	<string>FMWK</string>
+	<key>CFBundleShortVersionString</key>
+	<string>${VERSION}</string>
+	<key>CFBundleSignature</key>
+	<string>????</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>iPhoneOS</string>
+	</array>
+	<key>CFBundleVersion</key>
+	<string>${VERSION}</string>
+	<key>MinimumOSVersion</key>
+	<string>${IOS_VERSION_MIN}</string>
+	<key>UIDeviceFamily</key>
+	<array>
+		<integer>1</integer>
+		<integer>2</integer>
+	</array>
+	<key>VPXFullVersion</key>
+	<string>${FULLVERSION}</string>
+</dict>
+</plist>
diff --git a/src/third_party/libvpx/build/make/iosbuild.sh b/src/third_party/libvpx/build/make/iosbuild.sh
new file mode 100755
index 0000000..c703f22
--- /dev/null
+++ b/src/third_party/libvpx/build/make/iosbuild.sh
@@ -0,0 +1,383 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##
+## This script generates 'VPX.framework'. An iOS app can encode and decode VPx
+## video by including 'VPX.framework'.
+##
+## Run iosbuild.sh to create 'VPX.framework' in the current directory.
+##
+set -e
+devnull='> /dev/null 2>&1'
+
+BUILD_ROOT="_iosbuild"
+CONFIGURE_ARGS="--disable-docs
+                --disable-examples
+                --disable-libyuv
+                --disable-unit-tests"
+DIST_DIR="_dist"
+FRAMEWORK_DIR="VPX.framework"
+FRAMEWORK_LIB="VPX.framework/VPX"
+HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx"
+SCRIPT_DIR=$(dirname "$0")
+LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd)
+LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
+ORIG_PWD="$(pwd)"
+ARM_TARGETS="arm64-darwin-gcc
+             armv7-darwin-gcc
+             armv7s-darwin-gcc"
+SIM_TARGETS="x86-iphonesimulator-gcc
+             x86_64-iphonesimulator-gcc"
+OSX_TARGETS="x86-darwin15-gcc
+             x86_64-darwin15-gcc"
+TARGETS="${ARM_TARGETS} ${SIM_TARGETS}"
+
+# Configures for the target specified by $1, and invokes make with the dist
+# target using $DIST_DIR as the distribution output directory.
+build_target() {
+  local target="$1"
+  local old_pwd="$(pwd)"
+  local target_specific_flags=""
+
+  vlog "***Building target: ${target}***"
+
+  case "${target}" in
+    x86-*)
+      target_specific_flags="--enable-pic"
+      vlog "Enabled PIC for ${target}"
+      ;;
+  esac
+
+  mkdir "${target}"
+  cd "${target}"
+  eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \
+    ${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \
+    ${devnull}
+  export DIST_DIR
+  eval make dist ${devnull}
+  cd "${old_pwd}"
+
+  vlog "***Done building target: ${target}***"
+}
+
+# Returns the preprocessor symbol for the target specified by $1.
+target_to_preproc_symbol() {
+  target="$1"
+  case "${target}" in
+    arm64-*)
+      echo "__aarch64__"
+      ;;
+    armv7-*)
+      echo "__ARM_ARCH_7A__"
+      ;;
+    armv7s-*)
+      echo "__ARM_ARCH_7S__"
+      ;;
+    x86-*)
+      echo "__i386__"
+      ;;
+    x86_64-*)
+      echo "__x86_64__"
+      ;;
+    *)
+      echo "#error ${target} unknown/unsupported"
+      return 1
+      ;;
+  esac
+}
+
+# Create a vpx_config.h shim that, based on preprocessor settings for the
+# current target CPU, includes the real vpx_config.h for the current target.
+# $1 is the list of targets.
+create_vpx_framework_config_shim() {
+  local targets="$1"
+  local config_file="${HEADER_DIR}/vpx_config.h"
+  local preproc_symbol=""
+  local target=""
+  local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_"
+
+  local file_header="/*
+ *  Copyright (c) $(date +%Y) The WebM 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.
+ */
+
+/* GENERATED FILE: DO NOT EDIT! */
+
+#ifndef ${include_guard}
+#define ${include_guard}
+
+#if defined"
+
+  printf "%s" "${file_header}" > "${config_file}"
+  for target in ${targets}; do
+    preproc_symbol=$(target_to_preproc_symbol "${target}")
+    printf " ${preproc_symbol}\n" >> "${config_file}"
+    printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}"
+    printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}"
+    printf "#elif defined" >> "${config_file}"
+    mkdir "${HEADER_DIR}/${target}"
+    cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}"
+  done
+
+  # Consume the last line of output from the loop: We don't want it.
+  sed -i '' -e '$d' "${config_file}"
+
+  printf "#endif\n\n" >> "${config_file}"
+  printf "#endif  // ${include_guard}" >> "${config_file}"
+}
+
+# Verifies that $FRAMEWORK_LIB fat library contains requested builds.
+verify_framework_targets() {
+  local requested_cpus=""
+  local cpu=""
+
+  # Extract CPU from full target name.
+  for target; do
+    cpu="${target%%-*}"
+    if [ "${cpu}" = "x86" ]; then
+      # lipo -info outputs i386 for libvpx x86 targets.
+      cpu="i386"
+    fi
+    requested_cpus="${requested_cpus}${cpu} "
+  done
+
+  # Get target CPUs present in framework library.
+  local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB})
+
+  # $LIPO -info outputs a string like the following:
+  #   Architectures in the fat file: $FRAMEWORK_LIB <architectures>
+  # Capture only the architecture strings.
+  targets_built=${targets_built##*: }
+
+  # Sort CPU strings to make the next step a simple string compare.
+  local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ")
+  local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ")
+
+  vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}"
+  vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}"
+
+  if [ "${requested}" != "${actual}" ]; then
+    elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list."
+    elog "  Requested target CPUs: ${requested}"
+    elog "  Actual target CPUs: ${actual}"
+    return 1
+  fi
+}
+
+# Configures and builds each target specified by $1, and then builds
+# VPX.framework.
+build_framework() {
+  local lib_list=""
+  local targets="$1"
+  local target=""
+  local target_dist_dir=""
+
+  # Clean up from previous build(s).
+  rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}"
+
+  # Create output dirs.
+  mkdir -p "${BUILD_ROOT}"
+  mkdir -p "${HEADER_DIR}"
+
+  cd "${BUILD_ROOT}"
+
+  for target in ${targets}; do
+    build_target "${target}"
+    target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}"
+    if [ "${ENABLE_SHARED}" = "yes" ]; then
+      local suffix="dylib"
+    else
+      local suffix="a"
+    fi
+    lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.${suffix}"
+  done
+
+  cd "${ORIG_PWD}"
+
+  # The basic libvpx API includes are all the same; just grab the most recent
+  # set.
+  cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}"
+
+  # Build the fat library.
+  ${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX
+
+  # Create the vpx_config.h shim that allows usage of vpx_config.h from
+  # within VPX.framework.
+  create_vpx_framework_config_shim "${targets}"
+
+  # Copy in vpx_version.h.
+  cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}"
+
+  if [ "${ENABLE_SHARED}" = "yes" ]; then
+    # Adjust the dylib's name so dynamic linking in apps works as expected.
+    install_name_tool -id '@rpath/VPX.framework/VPX' ${FRAMEWORK_DIR}/VPX
+
+    # Copy in Info.plist.
+    cat "${SCRIPT_DIR}/ios-Info.plist" \
+      | sed "s/\${FULLVERSION}/${FULLVERSION}/g" \
+      | sed "s/\${VERSION}/${VERSION}/g" \
+      | sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \
+      > "${FRAMEWORK_DIR}/Info.plist"
+  fi
+
+  # Confirm VPX.framework/VPX contains the targets requested.
+  verify_framework_targets ${targets}
+
+  vlog "Created fat library ${FRAMEWORK_LIB} containing:"
+  for lib in ${lib_list}; do
+    vlog "  $(echo ${lib} | awk -F / '{print $2, $NF}')"
+  done
+}
+
+# Trap function. Cleans up the subtree used to build all targets contained in
+# $TARGETS.
+cleanup() {
+  local readonly res=$?
+  cd "${ORIG_PWD}"
+
+  if [ $res -ne 0 ]; then
+    elog "build exited with error ($res)"
+  fi
+
+  if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then
+    rm -rf "${BUILD_ROOT}"
+  fi
+}
+
+print_list() {
+  local indent="$1"
+  shift
+  local list="$@"
+  for entry in ${list}; do
+    echo "${indent}${entry}"
+  done
+}
+
+iosbuild_usage() {
+cat << EOF
+  Usage: ${0##*/} [arguments]
+    --help: Display this message and exit.
+    --enable-shared: Build a dynamic framework for use on iOS 8 or later.
+    --extra-configure-args <args>: Extra args to pass when configuring libvpx.
+    --macosx: Uses darwin15 targets instead of iphonesimulator targets for x86
+              and x86_64. Allows linking to framework when builds target MacOSX
+              instead of iOS.
+    --preserve-build-output: Do not delete the build directory.
+    --show-build-output: Show output from each library build.
+    --targets <targets>: Override default target list. Defaults:
+$(print_list "        " ${TARGETS})
+    --test-link: Confirms all targets can be linked. Functionally identical to
+                 passing --enable-examples via --extra-configure-args.
+    --verbose: Output information about the environment and each stage of the
+               build.
+EOF
+}
+
+elog() {
+  echo "${0##*/} failed because: $@" 1>&2
+}
+
+vlog() {
+  if [ "${VERBOSE}" = "yes" ]; then
+    echo "$@"
+  fi
+}
+
+trap cleanup EXIT
+
+# Parse the command line.
+while [ -n "$1" ]; do
+  case "$1" in
+    --extra-configure-args)
+      EXTRA_CONFIGURE_ARGS="$2"
+      shift
+      ;;
+    --help)
+      iosbuild_usage
+      exit
+      ;;
+    --enable-shared)
+      ENABLE_SHARED=yes
+      ;;
+    --preserve-build-output)
+      PRESERVE_BUILD_OUTPUT=yes
+      ;;
+    --show-build-output)
+      devnull=
+      ;;
+    --test-link)
+      EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples"
+      ;;
+    --targets)
+      TARGETS="$2"
+      shift
+      ;;
+    --macosx)
+      TARGETS="${ARM_TARGETS} ${OSX_TARGETS}"
+      ;;
+    --verbose)
+      VERBOSE=yes
+      ;;
+    *)
+      iosbuild_usage
+      exit 1
+      ;;
+  esac
+  shift
+done
+
+if [ "${ENABLE_SHARED}" = "yes" ]; then
+  CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}"
+fi
+
+FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBVPX_SOURCE_DIR}")
+VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')
+
+if [ "$ENABLE_SHARED" = "yes" ]; then
+  IOS_VERSION_OPTIONS="--enable-shared"
+  IOS_VERSION_MIN="8.0"
+else
+  IOS_VERSION_OPTIONS=""
+  IOS_VERSION_MIN="6.0"
+fi
+
+if [ "${VERBOSE}" = "yes" ]; then
+cat << EOF
+  BUILD_ROOT=${BUILD_ROOT}
+  DIST_DIR=${DIST_DIR}
+  CONFIGURE_ARGS=${CONFIGURE_ARGS}
+  EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS}
+  FRAMEWORK_DIR=${FRAMEWORK_DIR}
+  FRAMEWORK_LIB=${FRAMEWORK_LIB}
+  HEADER_DIR=${HEADER_DIR}
+  LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR}
+  LIPO=${LIPO}
+  MAKEFLAGS=${MAKEFLAGS}
+  ORIG_PWD=${ORIG_PWD}
+  PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
+  TARGETS="$(print_list "" ${TARGETS})"
+  ENABLE_SHARED=${ENABLE_SHARED}
+  OSX_TARGETS="${OSX_TARGETS}"
+  SIM_TARGETS="${SIM_TARGETS}"
+  SCRIPT_DIR="${SCRIPT_DIR}"
+  FULLVERSION="${FULLVERSION}"
+  VERSION="${VERSION}"
+  IOS_VERSION_MIN="${IOS_VERSION_MIN}"
+EOF
+fi
+
+build_framework "${TARGETS}"
+echo "Successfully built '${FRAMEWORK_DIR}' for:"
+print_list "" ${TARGETS}
diff --git a/src/third_party/libvpx/build/make/msvs_common.sh b/src/third_party/libvpx/build/make/msvs_common.sh
new file mode 100644
index 0000000..88f1cf9
--- /dev/null
+++ b/src/third_party/libvpx/build/make/msvs_common.sh
@@ -0,0 +1,114 @@
+#!/bin/bash
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+
+if [ "$(uname -o 2>/dev/null)" = "Cygwin" ] \
+   && cygpath --help >/dev/null 2>&1; then
+    FIXPATH='cygpath -m'
+else
+    FIXPATH='echo_path'
+fi
+
+die() {
+    echo "${self_basename}: $@" >&2
+    exit 1
+}
+
+die_unknown(){
+    echo "Unknown option \"$1\"." >&2
+    echo "See ${self_basename} --help for available options." >&2
+    exit 1
+}
+
+echo_path() {
+    for path; do
+        echo "$path"
+    done
+}
+
+# Output one, possibly changed based on the system, path per line.
+fix_path() {
+    $FIXPATH "$@"
+}
+
+# Corrects the paths in file_list in one pass for efficiency.
+# $1 is the name of the array to be modified.
+fix_file_list() {
+    declare -n array_ref=$1
+    files=$(fix_path "${array_ref[@]}")
+    local IFS=$'\n'
+    array_ref=($files)
+}
+
+generate_uuid() {
+    local hex="0123456789ABCDEF"
+    local i
+    local uuid=""
+    local j
+    #93995380-89BD-4b04-88EB-625FBE52EBFB
+    for ((i=0; i<32; i++)); do
+        (( j = $RANDOM % 16 ))
+        uuid="${uuid}${hex:$j:1}"
+    done
+    echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
+}
+
+indent1="    "
+indent=""
+indent_push() {
+    indent="${indent}${indent1}"
+}
+indent_pop() {
+    indent="${indent%${indent1}}"
+}
+
+tag_attributes() {
+    for opt in "$@"; do
+        optval="${opt#*=}"
+        [ -n "${optval}" ] ||
+            die "Missing attribute value in '$opt' while generating $tag tag"
+        echo "${indent}${opt%%=*}=\"${optval}\""
+    done
+}
+
+open_tag() {
+    local tag=$1
+    shift
+    if [ $# -ne 0 ]; then
+        echo "${indent}<${tag}"
+        indent_push
+        tag_attributes "$@"
+        echo "${indent}>"
+    else
+        echo "${indent}<${tag}>"
+        indent_push
+    fi
+}
+
+close_tag() {
+    local tag=$1
+    indent_pop
+    echo "${indent}</${tag}>"
+}
+
+tag() {
+    local tag=$1
+    shift
+    if [ $# -ne 0 ]; then
+        echo "${indent}<${tag}"
+        indent_push
+        tag_attributes "$@"
+        indent_pop
+        echo "${indent}/>"
+    else
+        echo "${indent}<${tag}/>"
+    fi
+}
+
diff --git a/src/third_party/libvpx/build/make/rtcd.pl b/src/third_party/libvpx/build/make/rtcd.pl
new file mode 100755
index 0000000..991b6ab
--- /dev/null
+++ b/src/third_party/libvpx/build/make/rtcd.pl
@@ -0,0 +1,426 @@
+#!/usr/bin/env perl
+
+no strict 'refs';
+use warnings;
+use Getopt::Long;
+Getopt::Long::Configure("auto_help") if $Getopt::Long::VERSION > 2.32;
+
+my %ALL_FUNCS = ();
+my @ALL_ARCHS;
+my @ALL_FORWARD_DECLS;
+my @REQUIRES;
+
+my %opts = ();
+my %disabled = ();
+my %required = ();
+
+my @argv;
+foreach (@ARGV) {
+  $disabled{$1} = 1, next if /--disable-(.*)/;
+  $required{$1} = 1, next if /--require-(.*)/;
+  push @argv, $_;
+}
+
+# NB: use GetOptions() instead of GetOptionsFromArray() for compatibility.
+@ARGV = @argv;
+GetOptions(
+  \%opts,
+  'arch=s',
+  'sym=s',
+  'config=s',
+);
+
+foreach my $opt (qw/arch config/) {
+  if (!defined($opts{$opt})) {
+    warn "--$opt is required!\n";
+    Getopt::Long::HelpMessage('-exit' => 1);
+  }
+}
+
+foreach my $defs_file (@ARGV) {
+  if (!-f $defs_file) {
+    warn "$defs_file: $!\n";
+    Getopt::Long::HelpMessage('-exit' => 1);
+  }
+}
+
+open CONFIG_FILE, $opts{config} or
+  die "Error opening config file '$opts{config}': $!\n";
+
+my %config = ();
+while (<CONFIG_FILE>) {
+  next if !/^(?:CONFIG_|HAVE_)/;
+  chomp;
+  my @pair = split /=/;
+  $config{$pair[0]} = $pair[1];
+}
+close CONFIG_FILE;
+
+#
+# Routines for the RTCD DSL to call
+#
+sub vpx_config($) {
+  return (defined $config{$_[0]}) ? $config{$_[0]} : "";
+}
+
+sub specialize {
+  my $fn=$_[0];
+  shift;
+  foreach my $opt (@_) {
+    eval "\$${fn}_${opt}=${fn}_${opt}";
+  }
+}
+
+sub add_proto {
+  my $fn = splice(@_, -2, 1);
+  $ALL_FUNCS{$fn} = \@_;
+  specialize $fn, "c";
+}
+
+sub require {
+  foreach my $fn (keys %ALL_FUNCS) {
+    foreach my $opt (@_) {
+      my $ofn = eval "\$${fn}_${opt}";
+      next if !$ofn;
+
+      # if we already have a default, then we can disable it, as we know
+      # we can do better.
+      my $best = eval "\$${fn}_default";
+      if ($best) {
+        my $best_ofn = eval "\$${best}";
+        if ($best_ofn && "$best_ofn" ne "$ofn") {
+          eval "\$${best}_link = 'false'";
+        }
+      }
+      eval "\$${fn}_default=${fn}_${opt}";
+      eval "\$${fn}_${opt}_link='true'";
+    }
+  }
+}
+
+sub forward_decls {
+  push @ALL_FORWARD_DECLS, @_;
+}
+
+#
+# Include the user's directives
+#
+foreach my $f (@ARGV) {
+  open FILE, "<", $f or die "cannot open $f: $!\n";
+  my $contents = join('', <FILE>);
+  close FILE;
+  eval $contents or warn "eval failed: $@\n";
+}
+
+#
+# Process the directives according to the command line
+#
+sub process_forward_decls() {
+  foreach (@ALL_FORWARD_DECLS) {
+    $_->();
+  }
+}
+
+sub determine_indirection {
+  vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS);
+  foreach my $fn (keys %ALL_FUNCS) {
+    my $n = "";
+    my @val = @{$ALL_FUNCS{$fn}};
+    my $args = pop @val;
+    my $rtyp = "@val";
+    my $dfn = eval "\$${fn}_default";
+    $dfn = eval "\$${dfn}";
+    foreach my $opt (@_) {
+      my $ofn = eval "\$${fn}_${opt}";
+      next if !$ofn;
+      my $link = eval "\$${fn}_${opt}_link";
+      next if $link && $link eq "false";
+      $n .= "x";
+    }
+    if ($n eq "x") {
+      eval "\$${fn}_indirect = 'false'";
+    } else {
+      eval "\$${fn}_indirect = 'true'";
+    }
+  }
+}
+
+sub declare_function_pointers {
+  foreach my $fn (sort keys %ALL_FUNCS) {
+    my @val = @{$ALL_FUNCS{$fn}};
+    my $args = pop @val;
+    my $rtyp = "@val";
+    my $dfn = eval "\$${fn}_default";
+    $dfn = eval "\$${dfn}";
+    foreach my $opt (@_) {
+      my $ofn = eval "\$${fn}_${opt}";
+      next if !$ofn;
+      print "$rtyp ${ofn}($args);\n";
+    }
+    if (eval "\$${fn}_indirect" eq "false") {
+      print "#define ${fn} ${dfn}\n";
+    } else {
+      print "RTCD_EXTERN $rtyp (*${fn})($args);\n";
+    }
+    print "\n";
+  }
+}
+
+sub set_function_pointers {
+  foreach my $fn (sort keys %ALL_FUNCS) {
+    my @val = @{$ALL_FUNCS{$fn}};
+    my $args = pop @val;
+    my $rtyp = "@val";
+    my $dfn = eval "\$${fn}_default";
+    $dfn = eval "\$${dfn}";
+    if (eval "\$${fn}_indirect" eq "true") {
+      print "    $fn = $dfn;\n";
+      foreach my $opt (@_) {
+        my $ofn = eval "\$${fn}_${opt}";
+        next if !$ofn;
+        next if "$ofn" eq "$dfn";
+        my $link = eval "\$${fn}_${opt}_link";
+        next if $link && $link eq "false";
+        my $cond = eval "\$have_${opt}";
+        print "    if (${cond}) $fn = $ofn;\n"
+      }
+    }
+  }
+}
+
+sub filter {
+  my @filtered;
+  foreach (@_) { push @filtered, $_ unless $disabled{$_}; }
+  return @filtered;
+}
+
+#
+# Helper functions for generating the arch specific RTCD files
+#
+sub common_top() {
+  my $include_guard = uc($opts{sym})."_H_";
+  print <<EOF;
+#ifndef ${include_guard}
+#define ${include_guard}
+
+#ifdef RTCD_C
+#define RTCD_EXTERN
+#else
+#define RTCD_EXTERN extern
+#endif
+
+EOF
+
+process_forward_decls();
+print <<EOF;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+declare_function_pointers("c", @ALL_ARCHS);
+
+print <<EOF;
+void $opts{sym}(void);
+
+EOF
+}
+
+sub common_bottom() {
+  print <<EOF;
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif
+EOF
+}
+
+sub x86() {
+  determine_indirection("c", @ALL_ARCHS);
+
+  # Assign the helper variable for each enabled extension
+  foreach my $opt (@ALL_ARCHS) {
+    my $opt_uc = uc $opt;
+    eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
+  }
+
+  common_top;
+  print <<EOF;
+#ifdef RTCD_C
+#include "vpx_ports/x86.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = x86_simd_caps();
+
+    (void)flags;
+
+EOF
+
+  set_function_pointers("c", @ALL_ARCHS);
+
+  print <<EOF;
+}
+#endif
+EOF
+  common_bottom;
+}
+
+sub arm() {
+  determine_indirection("c", @ALL_ARCHS);
+
+  # Assign the helper variable for each enabled extension
+  foreach my $opt (@ALL_ARCHS) {
+    my $opt_uc = uc $opt;
+    # Enable neon assembly based on HAVE_NEON logic instead of adding new
+    # HAVE_NEON_ASM logic
+    if ($opt eq 'neon_asm') { $opt_uc = 'NEON' }
+    eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
+  }
+
+  common_top;
+  print <<EOF;
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+#include "vpx_ports/arm.h"
+static void setup_rtcd_internal(void)
+{
+    int flags = arm_cpu_caps();
+
+    (void)flags;
+
+EOF
+
+  set_function_pointers("c", @ALL_ARCHS);
+
+  print <<EOF;
+}
+#endif
+EOF
+  common_bottom;
+}
+
+sub mips() {
+  determine_indirection("c", @ALL_ARCHS);
+  common_top;
+
+  print <<EOF;
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+static void setup_rtcd_internal(void)
+{
+EOF
+
+  set_function_pointers("c", @ALL_ARCHS);
+
+  print <<EOF;
+#if HAVE_DSPR2
+void vpx_dsputil_static_init();
+#if CONFIG_VP8
+void dsputil_static_init();
+#endif
+
+vpx_dsputil_static_init();
+#if CONFIG_VP8
+dsputil_static_init();
+#endif
+#endif
+}
+#endif
+EOF
+  common_bottom;
+}
+
+sub unoptimized() {
+  determine_indirection "c";
+  common_top;
+  print <<EOF;
+#include "vpx_config.h"
+
+#ifdef RTCD_C
+static void setup_rtcd_internal(void)
+{
+EOF
+
+  set_function_pointers "c";
+
+  print <<EOF;
+}
+#endif
+EOF
+  common_bottom;
+}
+
+#
+# Main Driver
+#
+
+&require("c");
+if ($opts{arch} eq 'x86') {
+  @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
+  x86;
+} elsif ($opts{arch} eq 'x86_64') {
+  @ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2/);
+  @REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/);
+  &require(@REQUIRES);
+  x86;
+} elsif ($opts{arch} eq 'mips32' || $opts{arch} eq 'mips64') {
+  @ALL_ARCHS = filter("$opts{arch}");
+  open CONFIG_FILE, $opts{config} or
+    die "Error opening config file '$opts{config}': $!\n";
+  while (<CONFIG_FILE>) {
+    if (/HAVE_DSPR2=yes/) {
+      @ALL_ARCHS = filter("$opts{arch}", qw/dspr2/);
+      last;
+    }
+    if (/HAVE_MSA=yes/) {
+      @ALL_ARCHS = filter("$opts{arch}", qw/msa/);
+      last;
+    }
+  }
+  close CONFIG_FILE;
+  mips;
+} elsif ($opts{arch} eq 'armv6') {
+  @ALL_ARCHS = filter(qw/media/);
+  arm;
+} elsif ($opts{arch} =~ /armv7\w?/) {
+  @ALL_ARCHS = filter(qw/media neon_asm neon/);
+  @REQUIRES = filter(keys %required ? keys %required : qw/media/);
+  &require(@REQUIRES);
+  arm;
+} elsif ($opts{arch} eq 'armv8' || $opts{arch} eq 'arm64' ) {
+  @ALL_ARCHS = filter(qw/neon/);
+  arm;
+} else {
+  unoptimized;
+}
+
+__END__
+
+=head1 NAME
+
+rtcd -
+
+=head1 SYNOPSIS
+
+Usage: rtcd.pl [options] FILE
+
+See 'perldoc rtcd.pl' for more details.
+
+=head1 DESCRIPTION
+
+Reads the Run Time CPU Detections definitions from FILE and generates a
+C header file on stdout.
+
+=head1 OPTIONS
+
+Options:
+  --arch=ARCH       Architecture to generate defs for (required)
+  --disable-EXT     Disable support for EXT extensions
+  --require-EXT     Require support for EXT extensions
+  --sym=SYMBOL      Unique symbol to use for RTCD initialization function
+  --config=FILE     File with CONFIG_FOO=yes lines to parse
diff --git a/src/third_party/libvpx/build/make/thumb.pm b/src/third_party/libvpx/build/make/thumb.pm
new file mode 100644
index 0000000..483c253
--- /dev/null
+++ b/src/third_party/libvpx/build/make/thumb.pm
@@ -0,0 +1,70 @@
+#!/usr/bin/env perl
+##
+##  Copyright (c) 2013 The WebM 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.
+##
+
+package thumb;
+
+sub FixThumbInstructions($$)
+{
+    my $short_branches = $_[1];
+    my $branch_shift_offset = $short_branches ? 1 : 0;
+
+    # Write additions with shifts, such as "add r10, r11, lsl #8",
+    # in three operand form, "add r10, r10, r11, lsl #8".
+    s/(add\s+)(r\d+),\s*(r\d+),\s*(lsl #\d+)/$1$2, $2, $3, $4/g;
+
+    # Convert additions with a non-constant shift into a sequence
+    # with left shift, addition and a right shift (to restore the
+    # register to the original value). Currently the right shift
+    # isn't necessary in the code base since the values in these
+    # registers aren't used, but doing the shift for consistency.
+    # This converts instructions such as "add r12, r12, r5, lsl r4"
+    # into the sequence "lsl r5, r4", "add r12, r12, r5", "lsr r5, r4".
+    s/^(\s*)(add)(\s+)(r\d+),\s*(r\d+),\s*(r\d+),\s*lsl (r\d+)/$1lsl$3$6, $7\n$1$2$3$4, $5, $6\n$1lsr$3$6, $7/g;
+
+    # Convert loads with right shifts in the indexing into a
+    # sequence of an add, load and sub. This converts
+    # "ldrb r4, [r9, lr, asr #1]" into "add r9, r9, lr, asr #1",
+    # "ldrb r9, [r9]", "sub r9, r9, lr, asr #1".
+    s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+),\s*(asr #\d+)\]/$1add $3$5, $5, $6, $7\n$1$2$3$4, [$5]\n$1sub $3$5, $5, $6, $7/g;
+
+    # Convert register indexing with writeback into a separate add
+    # instruction. This converts "ldrb r12, [r1, r2]!" into
+    # "ldrb r12, [r1, r2]", "add r1, r1, r2".
+    s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+)\]!/$1$2$3$4, [$5, $6]\n$1add $3$5, $6/g;
+
+    # Convert negative register indexing into separate sub/add instructions.
+    # This converts "ldrne r4, [src, -pstep, lsl #1]" into
+    # "subne src, src, pstep, lsl #1", "ldrne r4, [src]",
+    # "addne src, src, pstep, lsl #1". In a couple of cases where
+    # this is used, it's used for two subsequent load instructions,
+    # where a hand-written version of it could merge two subsequent
+    # add and sub instructions.
+    s/^(\s*)((ldr|str|pld)(ne)?)(\s+)(r\d+,\s*)?\[(\w+), -([^\]]+)\]/$1sub$4$5$7, $7, $8\n$1$2$5$6\[$7\]\n$1add$4$5$7, $7, $8/g;
+
+    # Convert register post indexing to a separate add instruction.
+    # This converts "ldrneb r9, [r0], r2" into "ldrneb r9, [r0]",
+    # "addne r0, r0, r2".
+    s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g;
+
+    # Convert a conditional addition to the pc register into a series of
+    # instructions. This converts "addlt pc, pc, r3, lsl #2" into
+    # "itttt lt", "movlt.n r12, pc", "addlt.w r12, #12",
+    # "addlt.w r12, r12, r3, lsl #2", "movlt.n pc, r12".
+    # This assumes that r12 is free at this point.
+    s/^(\s*)addlt(\s+)pc,\s*pc,\s*(\w+),\s*lsl\s*#(\d+)/$1itttt$2lt\n$1movlt.n$2r12, pc\n$1addlt.w$2r12, #12\n$1addlt.w$2r12, r12, $3, lsl #($4-$branch_shift_offset)\n$1movlt.n$2pc, r12/g;
+
+    # Convert "mov pc, lr" into "bx lr", since the former only works
+    # for switching from arm to thumb (and only in armv7), but not
+    # from thumb to arm.
+    s/mov(\s*)pc\s*,\s*lr/bx$1lr/g;
+}
+
+1;
diff --git a/src/third_party/libvpx/build/make/version.sh b/src/third_party/libvpx/build/make/version.sh
new file mode 100755
index 0000000..6967527
--- /dev/null
+++ b/src/third_party/libvpx/build/make/version.sh
@@ -0,0 +1,77 @@
+#!/bin/sh
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+
+for opt in "$@"; do
+    optval="${opt#*=}"
+    case "$opt" in
+    --bare) bare=true ;;
+    *) break ;;
+    esac
+    shift
+done
+source_path=${1:-.}
+out_file=${2}
+id=${3:-VERSION_STRING}
+
+git_version_id=""
+if [ -e "${source_path}/.git" ]; then
+    # Source Path is a git working copy. Check for local modifications.
+    # Note that git submodules may have a file as .git, not a directory.
+    export GIT_DIR="${source_path}/.git"
+    git_version_id=`git describe --match=v[0-9]* 2>/dev/null`
+fi
+
+changelog_version=""
+for p in "${source_path}" "${source_path}/.."; do
+    if [ -z "$git_version_id" -a -f "${p}/CHANGELOG" ]; then
+        changelog_version=`head -n1 "${p}/CHANGELOG" | awk '{print $2}'`
+        changelog_version="${changelog_version}"
+        break
+    fi
+done
+version_str="${changelog_version}${git_version_id}"
+bare_version=${version_str#v}
+major_version=${bare_version%%.*}
+bare_version=${bare_version#*.}
+minor_version=${bare_version%%.*}
+bare_version=${bare_version#*.}
+patch_version=${bare_version%%-*}
+bare_version=${bare_version#${patch_version}}
+extra_version=${bare_version##-}
+
+#since they'll be used as integers below make sure they are or force to 0
+for v in major_version minor_version patch_version; do
+    if eval echo \$$v |grep -E -q '[^[:digit:]]'; then
+        eval $v=0
+    fi
+done
+
+if [ ${bare} ]; then
+    echo "${changelog_version}${git_version_id}" > $$.tmp
+else
+    cat<<EOF>$$.tmp
+#define VERSION_MAJOR  $major_version
+#define VERSION_MINOR  $minor_version
+#define VERSION_PATCH  $patch_version
+#define VERSION_EXTRA  "$extra_version"
+#define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
+#define ${id}_NOSP "${version_str}"
+#define ${id}      " ${version_str}"
+EOF
+fi
+if [ -n "$out_file" ]; then
+diff $$.tmp ${out_file} >/dev/null 2>&1 || cat $$.tmp > ${out_file}
+else
+cat $$.tmp
+fi
+rm $$.tmp
diff --git a/src/third_party/libvpx/codereview.settings b/src/third_party/libvpx/codereview.settings
new file mode 100644
index 0000000..d7c8d39
--- /dev/null
+++ b/src/third_party/libvpx/codereview.settings
@@ -0,0 +1,4 @@
+# This file is used by gcl to get repository specific information.
+GERRIT_HOST: chromium-review.googlesource.com
+GERRIT_PORT: 29418
+CODE_REVIEW_SERVER: chromium-review.googlesource.com
diff --git a/src/third_party/libvpx/configure b/src/third_party/libvpx/configure
new file mode 100755
index 0000000..fb6dfca
--- /dev/null
+++ b/src/third_party/libvpx/configure
@@ -0,0 +1,751 @@
+#!/bin/sh
+##
+##  configure
+##
+##  This script is the front-end to the build system. It provides a similar
+##  interface to standard configure scripts with some extra bits for dealing
+##  with toolchains that differ from the standard POSIX interface and
+##  for extracting subsets of the source tree. In theory, reusable parts
+##  of this script were intended to live in build/make/configure.sh,
+##  but in practice, the line is pretty blurry.
+##
+##  This build system is based in part on the FFmpeg configure script.
+##
+
+#source_path="`dirname \"$0\"`"
+source_path=${0%/*}
+. "${source_path}/build/make/configure.sh"
+
+show_help(){
+    show_help_pre
+    cat << EOF
+Advanced options:
+  ${toggle_libs}                  libraries
+  ${toggle_examples}              examples
+  ${toggle_docs}                  documentation
+  ${toggle_unit_tests}            unit tests
+  ${toggle_decode_perf_tests}     build decoder perf tests with unit tests
+  ${toggle_encode_perf_tests}     build encoder perf tests with unit tests
+  --cpu=CPU                       tune for the specified CPU (ARM: cortex-a8, X86: sse3)
+  --libc=PATH                     path to alternate libc
+  --size-limit=WxH                max size to allow in the decoder
+  --as={yasm|nasm|auto}           use specified assembler [auto, yasm preferred]
+  --sdk-path=PATH                 path to root of sdk (android builds only)
+  ${toggle_codec_srcs}            in/exclude codec library source code
+  ${toggle_debug_libs}            in/exclude debug version of libraries
+  ${toggle_static_msvcrt}         use static MSVCRT (VS builds only)
+  ${toggle_vp9_highbitdepth}      use VP9 high bit depth (10/12) profiles
+  ${toggle_better_hw_compatibility}
+                                  enable encoder to produce streams with better
+                                  hardware decoder compatibility
+  ${toggle_vp8}                   VP8 codec support
+  ${toggle_vp9}                   VP9 codec support
+  ${toggle_vp10}                  VP10 codec support
+  ${toggle_internal_stats}        output of encoder internal stats for debug, if supported (encoders)
+  ${toggle_postproc}              postprocessing
+  ${toggle_vp9_postproc}          vp9 specific postprocessing
+  ${toggle_multithread}           multithreaded encoding and decoding
+  ${toggle_spatial_resampling}    spatial sampling (scaling) support
+  ${toggle_realtime_only}         enable this option while building for real-time encoding
+  ${toggle_onthefly_bitpacking}   enable on-the-fly bitpacking in real-time encoding
+  ${toggle_error_concealment}     enable this option to get a decoder which is able to conceal losses
+  ${toggle_coefficient_range_checking}
+                                  enable decoder to check if intermediate
+                                  transform coefficients are in valid range
+  ${toggle_runtime_cpu_detect}    runtime cpu detection
+  ${toggle_shared}                shared library support
+  ${toggle_static}                static library support
+  ${toggle_small}                 favor smaller size over speed
+  ${toggle_postproc_visualizer}   macro block / block level visualizers
+  ${toggle_multi_res_encoding}    enable multiple-resolution encoding
+  ${toggle_temporal_denoising}    enable temporal denoising and disable the spatial denoiser
+  ${toggle_vp9_temporal_denoising}
+                                  enable vp9 temporal denoising
+  ${toggle_webm_io}               enable input from and output to WebM container
+  ${toggle_libyuv}                enable libyuv
+
+Codecs:
+  Codecs can be selectively enabled or disabled individually, or by family:
+      --disable-<codec>
+  is equivalent to:
+      --disable-<codec>-encoder
+      --disable-<codec>-decoder
+
+  Codecs available in this distribution:
+EOF
+#restore editor state '
+
+    family="";
+    last_family="";
+    c="";
+    str="";
+    for c in ${CODECS}; do
+        family=${c%_*}
+        if [ "${family}" != "${last_family}" ]; then
+            [ -z "${str}" ] || echo "${str}"
+            str="$(printf '    %10s:' ${family})"
+        fi
+        str="${str} $(printf '%10s' ${c#*_})"
+        last_family=${family}
+    done
+    echo "${str}"
+    show_help_post
+}
+
+##
+## BEGIN APPLICATION SPECIFIC CONFIGURATION
+##
+
+# all_platforms is a list of all supported target platforms. Maintain
+# alphabetically by architecture, generic-gnu last.
+all_platforms="${all_platforms} armv6-linux-rvct"
+all_platforms="${all_platforms} armv6-linux-gcc"
+all_platforms="${all_platforms} armv6-none-rvct"
+all_platforms="${all_platforms} arm64-darwin-gcc"
+all_platforms="${all_platforms} arm64-linux-gcc"
+all_platforms="${all_platforms} armv7-android-gcc"   #neon Cortex-A8
+all_platforms="${all_platforms} armv7-darwin-gcc"    #neon Cortex-A8
+all_platforms="${all_platforms} armv7-linux-rvct"    #neon Cortex-A8
+all_platforms="${all_platforms} armv7-linux-gcc"     #neon Cortex-A8
+all_platforms="${all_platforms} armv7-none-rvct"     #neon Cortex-A8
+all_platforms="${all_platforms} armv7-win32-vs11"
+all_platforms="${all_platforms} armv7-win32-vs12"
+all_platforms="${all_platforms} armv7-win32-vs14"
+all_platforms="${all_platforms} armv7s-darwin-gcc"
+all_platforms="${all_platforms} mips32-linux-gcc"
+all_platforms="${all_platforms} mips64-linux-gcc"
+all_platforms="${all_platforms} sparc-solaris-gcc"
+all_platforms="${all_platforms} x86-android-gcc"
+all_platforms="${all_platforms} x86-darwin8-gcc"
+all_platforms="${all_platforms} x86-darwin8-icc"
+all_platforms="${all_platforms} x86-darwin9-gcc"
+all_platforms="${all_platforms} x86-darwin9-icc"
+all_platforms="${all_platforms} x86-darwin10-gcc"
+all_platforms="${all_platforms} x86-darwin11-gcc"
+all_platforms="${all_platforms} x86-darwin12-gcc"
+all_platforms="${all_platforms} x86-darwin13-gcc"
+all_platforms="${all_platforms} x86-darwin14-gcc"
+all_platforms="${all_platforms} x86-darwin15-gcc"
+all_platforms="${all_platforms} x86-iphonesimulator-gcc"
+all_platforms="${all_platforms} x86-linux-gcc"
+all_platforms="${all_platforms} x86-linux-icc"
+all_platforms="${all_platforms} x86-os2-gcc"
+all_platforms="${all_platforms} x86-solaris-gcc"
+all_platforms="${all_platforms} x86-win32-gcc"
+all_platforms="${all_platforms} x86-win32-vs7"
+all_platforms="${all_platforms} x86-win32-vs8"
+all_platforms="${all_platforms} x86-win32-vs9"
+all_platforms="${all_platforms} x86-win32-vs10"
+all_platforms="${all_platforms} x86-win32-vs11"
+all_platforms="${all_platforms} x86-win32-vs12"
+all_platforms="${all_platforms} x86-win32-vs14"
+all_platforms="${all_platforms} x86_64-android-gcc"
+all_platforms="${all_platforms} x86_64-darwin9-gcc"
+all_platforms="${all_platforms} x86_64-darwin10-gcc"
+all_platforms="${all_platforms} x86_64-darwin11-gcc"
+all_platforms="${all_platforms} x86_64-darwin12-gcc"
+all_platforms="${all_platforms} x86_64-darwin13-gcc"
+all_platforms="${all_platforms} x86_64-darwin14-gcc"
+all_platforms="${all_platforms} x86_64-darwin15-gcc"
+all_platforms="${all_platforms} x86_64-iphonesimulator-gcc"
+all_platforms="${all_platforms} x86_64-linux-gcc"
+all_platforms="${all_platforms} x86_64-linux-icc"
+all_platforms="${all_platforms} x86_64-orbis-clang"
+all_platforms="${all_platforms} x86_64-solaris-gcc"
+all_platforms="${all_platforms} x86_64-win64-gcc"
+all_platforms="${all_platforms} x86_64-win64-vs8"
+all_platforms="${all_platforms} x86_64-win64-vs9"
+all_platforms="${all_platforms} x86_64-win64-vs10"
+all_platforms="${all_platforms} x86_64-win64-vs11"
+all_platforms="${all_platforms} x86_64-win64-vs12"
+all_platforms="${all_platforms} x86_64-win64-vs14"
+all_platforms="${all_platforms} generic-gnu"
+
+# all_targets is a list of all targets that can be configured
+# note that these should be in dependency order for now.
+all_targets="libs examples docs"
+
+# all targets available are enabled, by default.
+for t in ${all_targets}; do
+    [ -f "${source_path}/${t}.mk" ] && enable_feature ${t}
+done
+
+if ! perl --version >/dev/null; then
+    die "Perl is required to build"
+fi
+
+
+if [ "`cd \"${source_path}\" && pwd`" != "`pwd`" ]; then
+  # test to see if source_path already configured
+  if [ -f "${source_path}/vpx_config.h" ]; then
+    die "source directory already configured; run 'make distclean' there first"
+  fi
+fi
+
+# check installed doxygen version
+doxy_version=$(doxygen --version 2>/dev/null)
+doxy_major=${doxy_version%%.*}
+if [ ${doxy_major:-0} -ge 1 ]; then
+    doxy_version=${doxy_version#*.}
+    doxy_minor=${doxy_version%%.*}
+    doxy_patch=${doxy_version##*.}
+
+    [ $doxy_major -gt 1 ] && enable_feature doxygen
+    [ $doxy_minor -gt 5 ] && enable_feature doxygen
+    [ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable_feature doxygen
+fi
+
+# disable codecs when their source directory does not exist
+[ -d "${source_path}/vp8" ] || disable_codec vp8
+[ -d "${source_path}/vp9" ] || disable_codec vp9
+[ -d "${source_path}/vp10" ] || disable_codec vp10
+
+# disable vp10 codec by default
+disable_codec vp10
+
+# install everything except the sources, by default. sources will have
+# to be enabled when doing dist builds, since that's no longer a common
+# case.
+enabled doxygen && enable_feature install_docs
+enable_feature install_bins
+enable_feature install_libs
+
+enable_feature static
+enable_feature optimizations
+enable_feature dependency_tracking
+enable_feature spatial_resampling
+enable_feature multithread
+enable_feature os_support
+enable_feature temporal_denoising
+
+CODECS="
+    vp8_encoder
+    vp8_decoder
+    vp9_encoder
+    vp9_decoder
+    vp10_encoder
+    vp10_decoder
+"
+CODEC_FAMILIES="
+    vp8
+    vp9
+    vp10
+"
+
+ARCH_LIST="
+    arm
+    mips
+    x86
+    x86_64
+"
+ARCH_EXT_LIST_X86="
+    mmx
+    sse
+    sse2
+    sse3
+    ssse3
+    sse4_1
+    avx
+    avx2
+"
+ARCH_EXT_LIST="
+    edsp
+    media
+    neon
+    neon_asm
+
+    mips32
+    dspr2
+    msa
+    mips64
+
+    ${ARCH_EXT_LIST_X86}
+"
+HAVE_LIST="
+    ${ARCH_EXT_LIST}
+    vpx_ports
+    pthread_h
+    unistd_h
+"
+EXPERIMENT_LIST="
+    spatial_svc
+    fp_mb_stats
+    emulate_hardware
+    misc_fixes
+"
+CONFIG_LIST="
+    dependency_tracking
+    external_build
+    install_docs
+    install_bins
+    install_libs
+    install_srcs
+    use_x86inc
+    debug
+    gprof
+    gcov
+    rvct
+    gcc
+    msvs
+    pic
+    big_endian
+
+    codec_srcs
+    debug_libs
+
+    dequant_tokens
+    dc_recon
+    runtime_cpu_detect
+    postproc
+    vp9_postproc
+    multithread
+    internal_stats
+    ${CODECS}
+    ${CODEC_FAMILIES}
+    encoders
+    decoders
+    static_msvcrt
+    spatial_resampling
+    realtime_only
+    onthefly_bitpacking
+    error_concealment
+    shared
+    static
+    small
+    postproc_visualizer
+    os_support
+    unit_tests
+    webm_io
+    libyuv
+    decode_perf_tests
+    encode_perf_tests
+    multi_res_encoding
+    temporal_denoising
+    vp9_temporal_denoising
+    coefficient_range_checking
+    vp9_highbitdepth
+    better_hw_compatibility
+    experimental
+    size_limit
+    ${EXPERIMENT_LIST}
+"
+CMDLINE_SELECT="
+    dependency_tracking
+    external_build
+    extra_warnings
+    werror
+    install_docs
+    install_bins
+    install_libs
+    install_srcs
+    debug
+    gprof
+    gcov
+    pic
+    use_x86inc
+    optimizations
+    ccache
+    runtime_cpu_detect
+    thumb
+
+    libs
+    examples
+    docs
+    libc
+    as
+    size_limit
+    codec_srcs
+    debug_libs
+
+    dequant_tokens
+    dc_recon
+    postproc
+    vp9_postproc
+    multithread
+    internal_stats
+    ${CODECS}
+    ${CODEC_FAMILIES}
+    static_msvcrt
+    spatial_resampling
+    realtime_only
+    onthefly_bitpacking
+    error_concealment
+    shared
+    static
+    small
+    postproc_visualizer
+    unit_tests
+    webm_io
+    libyuv
+    decode_perf_tests
+    encode_perf_tests
+    multi_res_encoding
+    temporal_denoising
+    vp9_temporal_denoising
+    coefficient_range_checking
+    better_hw_compatibility
+    vp9_highbitdepth
+    experimental
+"
+
+process_cmdline() {
+    for opt do
+        optval="${opt#*=}"
+        case "$opt" in
+        --disable-codecs)
+          for c in ${CODEC_FAMILIES}; do disable_codec $c; done
+          ;;
+        --enable-?*|--disable-?*)
+        eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
+        if is_in ${option} ${EXPERIMENT_LIST}; then
+            if enabled experimental; then
+                ${action}_feature $option
+            else
+                log_echo "Ignoring $opt -- not in experimental mode."
+            fi
+        elif is_in ${option} "${CODECS} ${CODEC_FAMILIES}"; then
+            ${action}_codec ${option}
+        else
+            process_common_cmdline $opt
+        fi
+        ;;
+        *) process_common_cmdline "$opt"
+        ;;
+        esac
+    done
+}
+
+post_process_cmdline() {
+    c=""
+
+    # Enable all detected codecs, if they haven't been disabled
+    for c in ${CODECS}; do soft_enable $c; done
+
+    # Enable the codec family if any component of that family is enabled
+    for c in ${CODECS}; do
+        enabled $c && enable_feature ${c%_*}
+    done
+
+    # Set the {en,de}coders variable if any algorithm in that class is enabled
+    for c in ${CODECS}; do
+        enabled ${c} && enable_feature ${c##*_}s
+    done
+}
+
+
+process_targets() {
+    enabled child || write_common_config_banner
+    write_common_target_config_h ${BUILD_PFX}vpx_config.h
+    write_common_config_targets
+
+    # Calculate the default distribution name, based on the enabled features
+    cf=""
+    DIST_DIR=vpx
+    for cf in $CODEC_FAMILIES; do
+        if enabled ${cf}_encoder && enabled ${cf}_decoder; then
+            DIST_DIR="${DIST_DIR}-${cf}"
+        elif enabled ${cf}_encoder; then
+            DIST_DIR="${DIST_DIR}-${cf}cx"
+        elif enabled ${cf}_decoder; then
+            DIST_DIR="${DIST_DIR}-${cf}dx"
+        fi
+    done
+    enabled debug_libs && DIST_DIR="${DIST_DIR}-debug"
+    enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
+    ! enabled postproc && ! enabled vp9_postproc && DIST_DIR="${DIST_DIR}-nopost"
+    ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
+    ! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
+    DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
+    case "${tgt_os}" in
+    win*) enabled static_msvcrt && DIST_DIR="${DIST_DIR}mt" || DIST_DIR="${DIST_DIR}md"
+          DIST_DIR="${DIST_DIR}-${tgt_cc}"
+          ;;
+    esac
+    if [ -f "${source_path}/build/make/version.sh" ]; then
+        ver=`"$source_path/build/make/version.sh" --bare "$source_path"`
+        DIST_DIR="${DIST_DIR}-${ver}"
+        VERSION_STRING=${ver}
+        ver=${ver%%-*}
+        VERSION_PATCH=${ver##*.}
+        ver=${ver%.*}
+        VERSION_MINOR=${ver##*.}
+        ver=${ver#v}
+        VERSION_MAJOR=${ver%.*}
+    fi
+    enabled child || cat <<EOF >> config.mk
+
+PREFIX=${prefix}
+ifeq (\$(MAKECMDGOALS),dist)
+DIST_DIR?=${DIST_DIR}
+else
+DIST_DIR?=\$(DESTDIR)${prefix}
+endif
+LIBSUBDIR=${libdir##${prefix}/}
+
+VERSION_STRING=${VERSION_STRING}
+
+VERSION_MAJOR=${VERSION_MAJOR}
+VERSION_MINOR=${VERSION_MINOR}
+VERSION_PATCH=${VERSION_PATCH}
+
+CONFIGURE_ARGS=${CONFIGURE_ARGS}
+EOF
+    enabled child || echo "CONFIGURE_ARGS?=${CONFIGURE_ARGS}" >> config.mk
+
+    #
+    # Write makefiles for all enabled targets
+    #
+    for tgt in libs examples docs solution; do
+        tgt_fn="$tgt-$toolchain.mk"
+
+        if enabled $tgt; then
+            echo "Creating makefiles for ${toolchain} ${tgt}"
+            write_common_target_config_mk $tgt_fn ${BUILD_PFX}vpx_config.h
+            #write_${tgt}_config
+        fi
+    done
+
+}
+
+process_detect() {
+    if enabled shared; then
+        # Can only build shared libs on a subset of platforms. Doing this check
+        # here rather than at option parse time because the target auto-detect
+        # magic happens after the command line has been parsed.
+        case "${tgt_os}" in
+        linux|os2|darwin*|iphonesimulator*)
+            # Supported platforms
+            ;;
+        *)
+            if enabled gnu; then
+                echo "--enable-shared is only supported on ELF; assuming this is OK"
+            else
+                die "--enable-shared only supported on ELF, OS/2, and Darwin for now"
+            fi
+            ;;
+        esac
+    fi
+    if [ -z "$CC" ] || enabled external_build; then
+        echo "Bypassing toolchain for environment detection."
+        enable_feature external_build
+        check_header() {
+            log fake_check_header "$@"
+            header=$1
+            shift
+            var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
+            disable_feature $var
+            # Headers common to all environments
+            case $header in
+                stdio.h)
+                    true;
+                ;;
+                *)
+                    result=false
+                    for d in "$@"; do
+                        [ -f "${d##-I}/$header" ] && result=true && break
+                    done
+                    ${result:-true}
+            esac && enable_feature $var
+
+            # Specialize windows and POSIX environments.
+            case $toolchain in
+                *-win*-*)
+                    # Don't check for any headers in Windows builds.
+                    false
+                ;;
+                *)
+                    case $header in
+                        pthread.h) true;;
+                        unistd.h) true;;
+                        *) false;;
+                    esac && enable_feature $var
+            esac
+            enabled $var
+        }
+        check_ld() {
+            true
+        }
+    fi
+    check_header stdio.h || die "Unable to invoke compiler: ${CC} ${CFLAGS}"
+    check_ld <<EOF || die "Toolchain is unable to link executables"
+int main(void) {return 0;}
+EOF
+    # check system headers
+    check_header pthread.h
+    check_header unistd.h # for sysconf(3) and friends.
+
+    check_header vpx/vpx_integer.h -I${source_path} && enable_feature vpx_ports
+}
+
+process_toolchain() {
+    process_common_toolchain
+
+    # Enable some useful compiler flags
+    if enabled gcc; then
+        enabled werror && check_add_cflags -Werror
+        check_add_cflags -Wall
+        check_add_cflags -Wdeclaration-after-statement
+        check_add_cflags -Wdisabled-optimization
+        check_add_cflags -Wpointer-arith
+        check_add_cflags -Wtype-limits
+        check_add_cflags -Wcast-qual
+        check_add_cflags -Wvla
+        check_add_cflags -Wimplicit-function-declaration
+        check_add_cflags -Wuninitialized
+        check_add_cflags -Wunused-variable
+        case ${CC} in
+          *clang*)
+              # libvpx and/or clang have issues with aliasing:
+              # https://code.google.com/p/webm/issues/detail?id=603
+              # work around them until they are fixed
+              check_add_cflags -fno-strict-aliasing
+          ;;
+          *) check_add_cflags -Wunused-but-set-variable ;;
+        esac
+        if enabled mips || [ -z "${INLINE}" ]; then
+          enabled extra_warnings || check_add_cflags -Wno-unused-function
+        else
+          check_add_cflags -Wunused-function
+        fi
+    fi
+
+    if enabled icc; then
+        enabled werror && check_add_cflags -Werror
+        check_add_cflags -Wall
+        check_add_cflags -Wpointer-arith
+
+        # ICC has a number of floating point optimizations that we disable
+        # in favor of deterministic output WRT to other compilers
+        add_cflags -fp-model precise
+    fi
+
+    # Enable extra, harmless warnings. These might provide additional insight
+    # to what the compiler is doing and why, but in general, but they shouldn't
+    # be treated as fatal, even if we're treating warnings as errors.
+    GCC_EXTRA_WARNINGS="
+        -Wdisabled-optimization
+        -Winline
+    "
+    enabled gcc && EXTRA_WARNINGS="${GCC_EXTRA_WARNINGS}"
+    RVCT_EXTRA_WARNINGS="
+        --remarks
+    "
+    enabled rvct && EXTRA_WARNINGS="${RVCT_EXTRA_WARNINGS}"
+    if enabled extra_warnings; then
+        for w in ${EXTRA_WARNINGS}; do
+            check_add_cflags ${w}
+            enabled gcc && enabled werror && check_add_cflags -Wno-error=${w}
+        done
+    fi
+
+    # ccache only really works on gcc toolchains
+    enabled gcc || soft_disable ccache
+    if enabled mips; then
+        enable_feature dequant_tokens
+        enable_feature dc_recon
+    fi
+
+    if enabled internal_stats; then
+        enable_feature vp9_postproc
+    fi
+
+    # Enable the postbuild target if building for visual studio.
+    case "$tgt_cc" in
+        vs*) enable_feature msvs
+             enable_feature solution
+             vs_version=${tgt_cc##vs}
+             case $vs_version in
+             [789])
+                 VCPROJ_SFX=vcproj
+                 gen_vcproj_cmd=${source_path}/build/make/gen_msvs_proj.sh
+                 ;;
+             10|11|12|14)
+                 VCPROJ_SFX=vcxproj
+                 gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
+                 enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror"
+                 ;;
+             esac
+             all_targets="${all_targets} solution"
+             INLINE="__forceinline"
+        ;;
+    esac
+
+    # Other toolchain specific defaults
+    case $toolchain in x86*) soft_enable postproc;; esac
+
+    if enabled postproc_visualizer; then
+        enabled postproc || die "postproc_visualizer requires postproc to be enabled"
+    fi
+
+    # Enable unit tests by default if we have a working C++ compiler.
+    case "$toolchain" in
+        *-vs*)
+            soft_enable unit_tests
+            soft_enable webm_io
+            soft_enable libyuv
+        ;;
+        *-android-*)
+            soft_enable webm_io
+            soft_enable libyuv
+            # GTestLog must be modified to use Android logging utilities.
+        ;;
+        *-darwin-*)
+            # iOS/ARM builds do not work with gtest. This does not match
+            # x86 targets.
+        ;;
+        *-iphonesimulator-*)
+            soft_enable webm_io
+            soft_enable libyuv
+        ;;
+        *-win*)
+            # Some mingw toolchains don't have pthread available by default.
+            # Treat these more like visual studio where threading in gtest
+            # would be disabled for the same reason.
+            check_cxx "$@" <<EOF && soft_enable unit_tests
+int z;
+EOF
+            check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
+            check_cxx "$@" <<EOF && soft_enable libyuv
+int z;
+EOF
+        ;;
+        *)
+            enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
+int z;
+EOF
+            check_cxx "$@" <<EOF && soft_enable webm_io
+int z;
+EOF
+            check_cxx "$@" <<EOF && soft_enable libyuv
+int z;
+EOF
+        ;;
+    esac
+    # libwebm needs to be linked with C++ standard library
+    enabled webm_io && LD=${CXX}
+
+    # append any user defined extra cflags
+    if [ -n "${extra_cflags}" ] ; then
+        check_add_cflags ${extra_cflags} || \
+        die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
+    fi
+    if [ -n "${extra_cxxflags}" ]; then
+        check_add_cxxflags ${extra_cxxflags} || \
+        die "Requested extra CXXFLAGS '${extra_cxxflags}' not supported by compiler"
+    fi
+}
+
+
+##
+## END APPLICATION SPECIFIC CONFIGURATION
+##
+CONFIGURE_ARGS="$@"
+process "$@"
+print_webm_license ${BUILD_PFX}vpx_config.c "/*" " */"
+cat <<EOF >> ${BUILD_PFX}vpx_config.c
+#include "vpx/vpx_codec.h"
+static const char* const cfg = "$CONFIGURE_ARGS";
+const char *vpx_codec_build_config(void) {return cfg;}
+EOF
diff --git a/src/third_party/libvpx/docs.mk b/src/third_party/libvpx/docs.mk
new file mode 100644
index 0000000..889d182
--- /dev/null
+++ b/src/third_party/libvpx/docs.mk
@@ -0,0 +1,48 @@
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+INSTALL_MAPS += docs/%    docs/%
+INSTALL_MAPS += src/%     %
+INSTALL_MAPS += %         %
+
+# Static documentation authored in doxygen
+CODEC_DOX :=    mainpage.dox \
+		keywords.dox \
+		usage.dox \
+		usage_cx.dox \
+		usage_dx.dox \
+
+# Other doxy files sourced in Markdown
+TXT_DOX = $(call enabled,TXT_DOX)
+
+EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
+EXAMPLE_PATH += $(SRC_PATH_BARE)/examples
+
+doxyfile: $(if $(findstring examples, $(ALL_TARGETS)),examples.doxy)
+doxyfile: libs.doxy_template libs.doxy
+	@echo "    [CREATE] $@"
+	@cat $^ > $@
+	@echo "STRIP_FROM_PATH += $(SRC_PATH_BARE) $(BUILD_ROOT)" >> $@
+	@echo "INPUT += $(addprefix $(SRC_PATH_BARE)/,$(CODEC_DOX))" >> $@;
+	@echo "INPUT += $(TXT_DOX)" >> $@;
+	@echo "EXAMPLE_PATH += $(EXAMPLE_PATH)" >> $@
+
+CLEAN-OBJS += doxyfile $(wildcard docs/html/*)
+docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX)
+	@echo "    [DOXYGEN] $<"
+	@doxygen $<
+DOCS-yes += docs/html/index.html
+
+DIST-DOCS-yes = $(wildcard docs/html/*)
+DIST-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
+DIST-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
+DIST-DOCS-yes                  += CHANGELOG
+DIST-DOCS-yes                  += README
diff --git a/src/third_party/libvpx/examples.mk b/src/third_party/libvpx/examples.mk
new file mode 100644
index 0000000..c891a54
--- /dev/null
+++ b/src/third_party/libvpx/examples.mk
@@ -0,0 +1,393 @@
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+LIBYUV_SRCS +=  third_party/libyuv/include/libyuv/basic_types.h  \
+                third_party/libyuv/include/libyuv/convert.h \
+                third_party/libyuv/include/libyuv/convert_argb.h \
+                third_party/libyuv/include/libyuv/convert_from.h \
+                third_party/libyuv/include/libyuv/cpu_id.h  \
+                third_party/libyuv/include/libyuv/planar_functions.h  \
+                third_party/libyuv/include/libyuv/rotate.h  \
+                third_party/libyuv/include/libyuv/row.h  \
+                third_party/libyuv/include/libyuv/scale.h  \
+                third_party/libyuv/include/libyuv/scale_row.h  \
+                third_party/libyuv/source/cpu_id.cc \
+                third_party/libyuv/source/planar_functions.cc \
+                third_party/libyuv/source/row_any.cc \
+                third_party/libyuv/source/row_common.cc \
+                third_party/libyuv/source/row_gcc.cc \
+                third_party/libyuv/source/row_mips.cc \
+                third_party/libyuv/source/row_neon.cc \
+                third_party/libyuv/source/row_neon64.cc \
+                third_party/libyuv/source/row_win.cc \
+                third_party/libyuv/source/scale.cc \
+                third_party/libyuv/source/scale_any.cc \
+                third_party/libyuv/source/scale_common.cc \
+                third_party/libyuv/source/scale_gcc.cc \
+                third_party/libyuv/source/scale_mips.cc \
+                third_party/libyuv/source/scale_neon.cc \
+                third_party/libyuv/source/scale_neon64.cc \
+                third_party/libyuv/source/scale_win.cc \
+
+LIBWEBM_COMMON_SRCS += third_party/libwebm/common/hdr_util.cc \
+                       third_party/libwebm/common/hdr_util.h \
+                       third_party/libwebm/common/webmids.h
+
+LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer/mkvmuxer.cc \
+                      third_party/libwebm/mkvmuxer/mkvmuxerutil.cc \
+                      third_party/libwebm/mkvmuxer/mkvwriter.cc \
+                      third_party/libwebm/mkvmuxer/mkvmuxer.h \
+                      third_party/libwebm/mkvmuxer/mkvmuxertypes.h \
+                      third_party/libwebm/mkvmuxer/mkvmuxerutil.h \
+                      third_party/libwebm/mkvparser/mkvparser.h \
+                      third_party/libwebm/mkvmuxer/mkvwriter.h
+
+LIBWEBM_PARSER_SRCS = third_party/libwebm/mkvparser/mkvparser.cc \
+                      third_party/libwebm/mkvparser/mkvreader.cc \
+                      third_party/libwebm/mkvparser/mkvparser.h \
+                      third_party/libwebm/mkvparser/mkvreader.h
+
+# Add compile flags and include path for libwebm sources.
+ifeq ($(CONFIG_WEBM_IO),yes)
+  CXXFLAGS     += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
+  INC_PATH-yes += $(SRC_PATH_BARE)/third_party/libwebm
+endif
+
+
+# List of examples to build. UTILS are tools meant for distribution
+# while EXAMPLES demonstrate specific portions of the API.
+UTILS-$(CONFIG_DECODERS)    += vpxdec.c
+vpxdec.SRCS                 += md5_utils.c md5_utils.h
+vpxdec.SRCS                 += vpx_ports/mem_ops.h
+vpxdec.SRCS                 += vpx_ports/mem_ops_aligned.h
+vpxdec.SRCS                 += vpx_ports/msvc.h
+vpxdec.SRCS                 += vpx_ports/vpx_timer.h
+vpxdec.SRCS                 += vpx/vpx_integer.h
+vpxdec.SRCS                 += args.c args.h
+vpxdec.SRCS                 += ivfdec.c ivfdec.h
+vpxdec.SRCS                 += tools_common.c tools_common.h
+vpxdec.SRCS                 += y4menc.c y4menc.h
+ifeq ($(CONFIG_LIBYUV),yes)
+  vpxdec.SRCS                 += $(LIBYUV_SRCS)
+endif
+ifeq ($(CONFIG_WEBM_IO),yes)
+  vpxdec.SRCS                 += $(LIBWEBM_COMMON_SRCS)
+  vpxdec.SRCS                 += $(LIBWEBM_MUXER_SRCS)
+  vpxdec.SRCS                 += $(LIBWEBM_PARSER_SRCS)
+  vpxdec.SRCS                 += webmdec.cc webmdec.h
+endif
+vpxdec.GUID                  = BA5FE66F-38DD-E034-F542-B1578C5FB950
+vpxdec.DESCRIPTION           = Full featured decoder
+UTILS-$(CONFIG_ENCODERS)    += vpxenc.c
+vpxenc.SRCS                 += args.c args.h y4minput.c y4minput.h vpxenc.h
+vpxenc.SRCS                 += ivfdec.c ivfdec.h
+vpxenc.SRCS                 += ivfenc.c ivfenc.h
+vpxenc.SRCS                 += rate_hist.c rate_hist.h
+vpxenc.SRCS                 += tools_common.c tools_common.h
+vpxenc.SRCS                 += warnings.c warnings.h
+vpxenc.SRCS                 += vpx_ports/mem_ops.h
+vpxenc.SRCS                 += vpx_ports/mem_ops_aligned.h
+vpxenc.SRCS                 += vpx_ports/msvc.h
+vpxenc.SRCS                 += vpx_ports/vpx_timer.h
+vpxenc.SRCS                 += vpxstats.c vpxstats.h
+ifeq ($(CONFIG_LIBYUV),yes)
+  vpxenc.SRCS                 += $(LIBYUV_SRCS)
+endif
+ifeq ($(CONFIG_WEBM_IO),yes)
+  vpxenc.SRCS                 += $(LIBWEBM_COMMON_SRCS)
+  vpxenc.SRCS                 += $(LIBWEBM_MUXER_SRCS)
+  vpxenc.SRCS                 += $(LIBWEBM_PARSER_SRCS)
+  vpxenc.SRCS                 += webmenc.cc webmenc.h
+endif
+vpxenc.GUID                  = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
+vpxenc.DESCRIPTION           = Full featured encoder
+ifeq ($(CONFIG_SPATIAL_SVC),yes)
+  EXAMPLES-$(CONFIG_VP9_ENCODER)      += vp9_spatial_svc_encoder.c
+  vp9_spatial_svc_encoder.SRCS        += args.c args.h
+  vp9_spatial_svc_encoder.SRCS        += ivfenc.c ivfenc.h
+  vp9_spatial_svc_encoder.SRCS        += tools_common.c tools_common.h
+  vp9_spatial_svc_encoder.SRCS        += video_common.h
+  vp9_spatial_svc_encoder.SRCS        += video_writer.h video_writer.c
+  vp9_spatial_svc_encoder.SRCS        += vpx_ports/msvc.h
+  vp9_spatial_svc_encoder.SRCS        += vpxstats.c vpxstats.h
+  vp9_spatial_svc_encoder.GUID        = 4A38598D-627D-4505-9C7B-D4020C84100D
+  vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder
+endif
+
+ifneq ($(CONFIG_SHARED),yes)
+EXAMPLES-$(CONFIG_VP9_ENCODER)    += resize_util.c
+endif
+
+EXAMPLES-$(CONFIG_ENCODERS)          += vpx_temporal_svc_encoder.c
+vpx_temporal_svc_encoder.SRCS        += ivfenc.c ivfenc.h
+vpx_temporal_svc_encoder.SRCS        += tools_common.c tools_common.h
+vpx_temporal_svc_encoder.SRCS        += video_common.h
+vpx_temporal_svc_encoder.SRCS        += video_writer.h video_writer.c
+vpx_temporal_svc_encoder.SRCS        += vpx_ports/msvc.h
+vpx_temporal_svc_encoder.GUID        = B18C08F2-A439-4502-A78E-849BE3D60947
+vpx_temporal_svc_encoder.DESCRIPTION = Temporal SVC Encoder
+EXAMPLES-$(CONFIG_DECODERS)        += simple_decoder.c
+simple_decoder.GUID                 = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
+simple_decoder.SRCS                += ivfdec.h ivfdec.c
+simple_decoder.SRCS                += tools_common.h tools_common.c
+simple_decoder.SRCS                += video_common.h
+simple_decoder.SRCS                += video_reader.h video_reader.c
+simple_decoder.SRCS                += vpx_ports/mem_ops.h
+simple_decoder.SRCS                += vpx_ports/mem_ops_aligned.h
+simple_decoder.SRCS                += vpx_ports/msvc.h
+simple_decoder.DESCRIPTION          = Simplified decoder loop
+EXAMPLES-$(CONFIG_DECODERS)        += postproc.c
+postproc.SRCS                      += ivfdec.h ivfdec.c
+postproc.SRCS                      += tools_common.h tools_common.c
+postproc.SRCS                      += video_common.h
+postproc.SRCS                      += video_reader.h video_reader.c
+postproc.SRCS                      += vpx_ports/mem_ops.h
+postproc.SRCS                      += vpx_ports/mem_ops_aligned.h
+postproc.SRCS                      += vpx_ports/msvc.h
+postproc.GUID                       = 65E33355-F35E-4088-884D-3FD4905881D7
+postproc.DESCRIPTION                = Decoder postprocessor control
+EXAMPLES-$(CONFIG_DECODERS)        += decode_to_md5.c
+decode_to_md5.SRCS                 += md5_utils.h md5_utils.c
+decode_to_md5.SRCS                 += ivfdec.h ivfdec.c
+decode_to_md5.SRCS                 += tools_common.h tools_common.c
+decode_to_md5.SRCS                 += video_common.h
+decode_to_md5.SRCS                 += video_reader.h video_reader.c
+decode_to_md5.SRCS                 += vpx_ports/mem_ops.h
+decode_to_md5.SRCS                 += vpx_ports/mem_ops_aligned.h
+decode_to_md5.SRCS                 += vpx_ports/msvc.h
+decode_to_md5.GUID                  = 59120B9B-2735-4BFE-B022-146CA340FE42
+decode_to_md5.DESCRIPTION           = Frame by frame MD5 checksum
+EXAMPLES-$(CONFIG_ENCODERS)     += simple_encoder.c
+simple_encoder.SRCS             += ivfenc.h ivfenc.c
+simple_encoder.SRCS             += tools_common.h tools_common.c
+simple_encoder.SRCS             += video_common.h
+simple_encoder.SRCS             += video_writer.h video_writer.c
+simple_encoder.SRCS             += vpx_ports/msvc.h
+simple_encoder.GUID              = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
+simple_encoder.DESCRIPTION       = Simplified encoder loop
+EXAMPLES-$(CONFIG_VP9_ENCODER)  += vp9_lossless_encoder.c
+vp9_lossless_encoder.SRCS       += ivfenc.h ivfenc.c
+vp9_lossless_encoder.SRCS       += tools_common.h tools_common.c
+vp9_lossless_encoder.SRCS       += video_common.h
+vp9_lossless_encoder.SRCS       += video_writer.h video_writer.c
+vp9_lossless_encoder.SRCS       += vpx_ports/msvc.h
+vp9_lossless_encoder.GUID        = B63C7C88-5348-46DC-A5A6-CC151EF93366
+vp9_lossless_encoder.DESCRIPTION = Simplified lossless VP9 encoder
+EXAMPLES-$(CONFIG_ENCODERS)     += twopass_encoder.c
+twopass_encoder.SRCS            += ivfenc.h ivfenc.c
+twopass_encoder.SRCS            += tools_common.h tools_common.c
+twopass_encoder.SRCS            += video_common.h
+twopass_encoder.SRCS            += video_writer.h video_writer.c
+twopass_encoder.SRCS            += vpx_ports/msvc.h
+twopass_encoder.GUID             = 73494FA6-4AF9-4763-8FBB-265C92402FD8
+twopass_encoder.DESCRIPTION      = Two-pass encoder loop
+EXAMPLES-$(CONFIG_DECODERS)     += decode_with_drops.c
+decode_with_drops.SRCS          += ivfdec.h ivfdec.c
+decode_with_drops.SRCS          += tools_common.h tools_common.c
+decode_with_drops.SRCS          += video_common.h
+decode_with_drops.SRCS          += video_reader.h video_reader.c
+decode_with_drops.SRCS          += vpx_ports/mem_ops.h
+decode_with_drops.SRCS          += vpx_ports/mem_ops_aligned.h
+decode_with_drops.SRCS          += vpx_ports/msvc.h
+decode_with_drops.GUID           = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
+decode_with_drops.DESCRIPTION    = Drops frames while decoding
+EXAMPLES-$(CONFIG_ENCODERS)        += set_maps.c
+set_maps.SRCS                      += ivfenc.h ivfenc.c
+set_maps.SRCS                      += tools_common.h tools_common.c
+set_maps.SRCS                      += video_common.h
+set_maps.SRCS                      += video_writer.h video_writer.c
+set_maps.SRCS                      += vpx_ports/msvc.h
+set_maps.GUID                       = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
+set_maps.DESCRIPTION                = Set active and ROI maps
+EXAMPLES-$(CONFIG_VP8_ENCODER)     += vp8cx_set_ref.c
+vp8cx_set_ref.SRCS                 += ivfenc.h ivfenc.c
+vp8cx_set_ref.SRCS                 += tools_common.h tools_common.c
+vp8cx_set_ref.SRCS                 += video_common.h
+vp8cx_set_ref.SRCS                 += video_writer.h video_writer.c
+vp8cx_set_ref.SRCS                 += vpx_ports/msvc.h
+vp8cx_set_ref.GUID                  = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
+vp8cx_set_ref.DESCRIPTION           = VP8 set encoder reference frame
+
+
+ifeq ($(CONFIG_MULTI_RES_ENCODING),yes)
+ifeq ($(CONFIG_LIBYUV),yes)
+EXAMPLES-$(CONFIG_VP8_ENCODER)          += vp8_multi_resolution_encoder.c
+vp8_multi_resolution_encoder.SRCS       += ivfenc.h ivfenc.c
+vp8_multi_resolution_encoder.SRCS       += tools_common.h tools_common.c
+vp8_multi_resolution_encoder.SRCS       += video_writer.h video_writer.c
+vp8_multi_resolution_encoder.SRCS       += vpx_ports/msvc.h
+vp8_multi_resolution_encoder.SRCS       += $(LIBYUV_SRCS)
+vp8_multi_resolution_encoder.GUID        = 04f8738e-63c8-423b-90fa-7c2703a374de
+vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
+endif
+endif
+
+# Handle extra library flags depending on codec configuration
+
+# We should not link to math library (libm) on RVCT
+# when building for bare-metal targets
+ifeq ($(CONFIG_OS_SUPPORT), yes)
+CODEC_EXTRA_LIBS-$(CONFIG_VP8)         += m
+CODEC_EXTRA_LIBS-$(CONFIG_VP9)         += m
+else
+    ifeq ($(CONFIG_GCC), yes)
+    CODEC_EXTRA_LIBS-$(CONFIG_VP8)         += m
+    CODEC_EXTRA_LIBS-$(CONFIG_VP9)         += m
+    endif
+endif
+#
+# End of specified files. The rest of the build rules should happen
+# automagically from here.
+#
+
+
+# Examples need different flags based on whether we're building
+# from an installed tree or a version controlled tree. Determine
+# the proper paths.
+ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
+    LIB_PATH-yes := $(SRC_PATH_BARE)/../lib
+    INC_PATH-yes := $(SRC_PATH_BARE)/../include
+else
+    LIB_PATH-yes                     += $(if $(BUILD_PFX),$(BUILD_PFX),.)
+    INC_PATH-$(CONFIG_VP8_DECODER)   += $(SRC_PATH_BARE)/vp8
+    INC_PATH-$(CONFIG_VP8_ENCODER)   += $(SRC_PATH_BARE)/vp8
+    INC_PATH-$(CONFIG_VP9_DECODER)   += $(SRC_PATH_BARE)/vp9
+    INC_PATH-$(CONFIG_VP9_ENCODER)   += $(SRC_PATH_BARE)/vp9
+endif
+INC_PATH-$(CONFIG_LIBYUV) += $(SRC_PATH_BARE)/third_party/libyuv/include
+LIB_PATH := $(call enabled,LIB_PATH)
+INC_PATH := $(call enabled,INC_PATH)
+INTERNAL_CFLAGS = $(addprefix -I,$(INC_PATH))
+INTERNAL_LDFLAGS += $(addprefix -L,$(LIB_PATH))
+
+
+# Expand list of selected examples to build (as specified above)
+UTILS           = $(call enabled,UTILS)
+EXAMPLES        = $(addprefix examples/,$(call enabled,EXAMPLES))
+ALL_EXAMPLES    = $(UTILS) $(EXAMPLES)
+UTIL_SRCS       = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS))
+ALL_SRCS        = $(foreach ex,$(ALL_EXAMPLES),$($(notdir $(ex:.c=)).SRCS))
+CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
+
+
+# Expand all example sources into a variable containing all sources
+# for that example (not just them main one specified in UTILS/EXAMPLES)
+# and add this file to the list (for MSVS workspace generation)
+$(foreach ex,$(ALL_EXAMPLES),$(eval $(notdir $(ex:.c=)).SRCS += $(ex) examples.mk))
+
+
+# Create build/install dependencies for all examples. The common case
+# is handled here. The MSVS case is handled below.
+NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
+DIST-BINS-$(NOT_MSVS)      += $(addprefix bin/,$(ALL_EXAMPLES:.c=$(EXE_SFX)))
+INSTALL-BINS-$(NOT_MSVS)   += $(addprefix bin/,$(UTILS:.c=$(EXE_SFX)))
+DIST-SRCS-yes              += $(ALL_SRCS)
+INSTALL-SRCS-yes           += $(UTIL_SRCS)
+OBJS-$(NOT_MSVS)           += $(call objs,$(ALL_SRCS))
+BINS-$(NOT_MSVS)           += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=$(EXE_SFX)))
+
+
+# Instantiate linker template for all examples.
+CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
+ifneq ($(filter darwin%,$(TGT_OS)),)
+SHARED_LIB_SUF=.dylib
+else
+ifneq ($(filter os2%,$(TGT_OS)),)
+SHARED_LIB_SUF=_dll.a
+else
+SHARED_LIB_SUF=.so
+endif
+endif
+CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a)
+$(foreach bin,$(BINS-yes),\
+    $(eval $(bin):$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF))\
+    $(eval $(call linker_template,$(bin),\
+        $(call objs,$($(notdir $(bin:$(EXE_SFX)=)).SRCS)) \
+        -l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\
+        )))
+
+# The following pairs define a mapping of locations in the distribution
+# tree to locations in the source/build trees.
+INSTALL_MAPS += src/%.c   %.c
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+INSTALL_MAPS += bin/%     %
+INSTALL_MAPS += %         %
+
+
+# Set up additional MSVS environment
+ifeq ($(CONFIG_MSVS),yes)
+CODEC_LIB=$(if $(CONFIG_SHARED),vpx,$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd))
+# This variable uses deferred expansion intentionally, since the results of
+# $(wildcard) may change during the course of the Make.
+VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),bin/$(p)/%  $(p)/Release/%)
+endif
+
+# Build Visual Studio Projects. We use a template here to instantiate
+# explicit rules rather than using an implicit rule because we want to
+# leverage make's VPATH searching rather than specifying the paths on
+# each file in ALL_EXAMPLES. This has the unfortunate side effect that
+# touching the source files trigger a rebuild of the project files
+# even though there is no real dependency there (the dependency is on
+# the makefiles). We may want to revisit this.
+define vcproj_template
+$(1): $($(1:.$(VCPROJ_SFX)=).SRCS) vpx.$(VCPROJ_SFX)
+	$(if $(quiet),@echo "    [vcproj] $$@")
+	$(qexec)$$(GEN_VCPROJ)\
+            --exe\
+            --target=$$(TOOLCHAIN)\
+            --name=$$(@:.$(VCPROJ_SFX)=)\
+            --ver=$$(CONFIG_VS_VERSION)\
+            --proj-guid=$$($$(@:.$(VCPROJ_SFX)=).GUID)\
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            $$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \
+            $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) $$^
+endef
+ALL_EXAMPLES_BASENAME := $(notdir $(ALL_EXAMPLES))
+PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES_BASENAME:.c=.$(VCPROJ_SFX))
+INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\
+                               $(addprefix bin/$(p)/,$(ALL_EXAMPLES_BASENAME:.c=.exe)))
+$(foreach proj,$(call enabled,PROJECTS),\
+    $(eval $(call vcproj_template,$(proj))))
+
+#
+# Documentation Rules
+#
+%.dox: %.c
+	@echo "    [DOXY] $@"
+	@mkdir -p $(dir $@)
+	@echo "/*!\page example_$(@F:.dox=) $(@F:.dox=)" > $@
+	@echo "   \includelineno $(<F)" >> $@
+	@echo "*/" >> $@
+
+samples.dox: examples.mk
+	@echo "    [DOXY] $@"
+	@echo "/*!\page samples Sample Code" > $@
+	@echo "    This SDK includes a number of sample applications."\
+	      "Each sample documents a feature of the SDK in both prose"\
+	      "and the associated C code."\
+	      "The following samples are included: ">>$@
+	@$(foreach ex,$(sort $(notdir $(EXAMPLES:.c=))),\
+	   echo "     - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
+	@echo >> $@
+	@echo "    In addition, the SDK contains a number of utilities."\
+              "Since these utilities are built upon the concepts described"\
+              "in the sample code listed above, they are not documented in"\
+              "pieces like the samples are. Their source is included here"\
+              "for reference. The following utilities are included:" >> $@
+	@$(foreach ex,$(sort $(UTILS:.c=)),\
+	   echo "     - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
+	@echo "*/" >> $@
+
+CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
+DOCS-yes += examples.doxy samples.dox
+examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox)
+	@echo "INPUT += $^" > $@
diff --git a/src/third_party/libvpx/examples/decode_to_md5.c b/src/third_party/libvpx/examples/decode_to_md5.c
new file mode 100644
index 0000000..1ae7a4b
--- /dev/null
+++ b/src/third_party/libvpx/examples/decode_to_md5.c
@@ -0,0 +1,137 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+// Frame-by-frame MD5 Checksum
+// ===========================
+//
+// This example builds upon the simple decoder loop to show how checksums
+// of the decoded output can be generated. These are used for validating
+// decoder implementations against the reference implementation, for example.
+//
+// MD5 algorithm
+// -------------
+// The Message-Digest 5 (MD5) is a well known hash function. We have provided
+// an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
+// Algorithm for your use. Our implmentation only changes the interface of this
+// reference code. You must include the `md5_utils.h` header for access to these
+// functions.
+//
+// Processing The Decoded Data
+// ---------------------------
+// Each row of the image is passed to the MD5 accumulator. First the Y plane
+// is processed, then U, then V. It is important to honor the image's `stride`
+// values.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
+#include "../md5_utils.h"
+#include "../tools_common.h"
+#include "../video_reader.h"
+#include "./vpx_config.h"
+
+static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
+  int plane, y;
+  MD5Context md5;
+
+  MD5Init(&md5);
+
+  for (plane = 0; plane < 3; ++plane) {
+    const unsigned char *buf = img->planes[plane];
+    const int stride = img->stride[plane];
+    const int w = plane ? (img->d_w + 1) >> 1 : img->d_w;
+    const int h = plane ? (img->d_h + 1) >> 1 : img->d_h;
+
+    for (y = 0; y < h; ++y) {
+      MD5Update(&md5, buf, w);
+      buf += stride;
+    }
+  }
+
+  MD5Final(digest, &md5);
+}
+
+static void print_md5(FILE *stream, unsigned char digest[16]) {
+  int i;
+
+  for (i = 0; i < 16; ++i)
+    fprintf(stream, "%02x", digest[i]);
+}
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
+  exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+  int frame_cnt = 0;
+  FILE *outfile = NULL;
+  vpx_codec_ctx_t codec;
+  VpxVideoReader *reader = NULL;
+  const VpxVideoInfo *info = NULL;
+  const VpxInterface *decoder = NULL;
+
+  exec_name = argv[0];
+
+  if (argc != 3)
+    die("Invalid number of arguments.");
+
+  reader = vpx_video_reader_open(argv[1]);
+  if (!reader)
+    die("Failed to open %s for reading.", argv[1]);
+
+  if (!(outfile = fopen(argv[2], "wb")))
+    die("Failed to open %s for writing.", argv[2]);
+
+  info = vpx_video_reader_get_info(reader);
+
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
+    die("Unknown input codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
+
+  if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+    die_codec(&codec, "Failed to initialize decoder");
+
+  while (vpx_video_reader_read_frame(reader)) {
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = NULL;
+    size_t frame_size = 0;
+    const unsigned char *frame = vpx_video_reader_get_frame(reader,
+                                                            &frame_size);
+    if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
+      die_codec(&codec, "Failed to decode frame");
+
+    while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+      unsigned char digest[16];
+
+      get_image_md5(img, digest);
+      print_md5(outfile, digest);
+      fprintf(outfile, "  img-%dx%d-%04d.i420\n",
+              img->d_w, img->d_h, ++frame_cnt);
+    }
+  }
+
+  printf("Processed %d frames.\n", frame_cnt);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_reader_close(reader);
+
+  fclose(outfile);
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/decode_with_drops.c b/src/third_party/libvpx/examples/decode_with_drops.c
new file mode 100644
index 0000000..2233e47
--- /dev/null
+++ b/src/third_party/libvpx/examples/decode_with_drops.c
@@ -0,0 +1,152 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+// Decode With Drops Example
+// =========================
+//
+// This is an example utility which drops a series of frames, as specified
+// on the command line. This is useful for observing the error recovery
+// features of the codec.
+//
+// Usage
+// -----
+// This example adds a single argument to the `simple_decoder` example,
+// which specifies the range or pattern of frames to drop. The parameter is
+// parsed as follows:
+//
+// Dropping A Range Of Frames
+// --------------------------
+// To drop a range of frames, specify the starting frame and the ending
+// frame to drop, separated by a dash. The following command will drop
+// frames 5 through 10 (base 1).
+//
+//  $ ./decode_with_drops in.ivf out.i420 5-10
+//
+//
+// Dropping A Pattern Of Frames
+// ----------------------------
+// To drop a pattern of frames, specify the number of frames to drop and
+// the number of frames after which to repeat the pattern, separated by
+// a forward-slash. The following command will drop 3 of 7 frames.
+// Specifically, it will decode 4 frames, then drop 3 frames, and then
+// repeat.
+//
+//  $ ./decode_with_drops in.ivf out.i420 3/7
+//
+//
+// Extra Variables
+// ---------------
+// This example maintains the pattern passed on the command line in the
+// `n`, `m`, and `is_range` variables:
+//
+//
+// Making The Drop Decision
+// ------------------------
+// The example decides whether to drop the frame based on the current
+// frame number, immediately before decoding the frame.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
+#include "../tools_common.h"
+#include "../video_reader.h"
+#include "./vpx_config.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
+  exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+  int frame_cnt = 0;
+  FILE *outfile = NULL;
+  vpx_codec_ctx_t codec;
+  const VpxInterface *decoder = NULL;
+  VpxVideoReader *reader = NULL;
+  const VpxVideoInfo *info = NULL;
+  int n = 0;
+  int m = 0;
+  int is_range = 0;
+  char *nptr = NULL;
+
+  exec_name = argv[0];
+
+  if (argc != 4)
+    die("Invalid number of arguments.");
+
+  reader = vpx_video_reader_open(argv[1]);
+  if (!reader)
+    die("Failed to open %s for reading.", argv[1]);
+
+  if (!(outfile = fopen(argv[2], "wb")))
+    die("Failed to open %s for writing.", argv[2]);
+
+  n = strtol(argv[3], &nptr, 0);
+  m = strtol(nptr + 1, NULL, 0);
+  is_range = (*nptr == '-');
+  if (!n || !m || (*nptr != '-' && *nptr != '/'))
+    die("Couldn't parse pattern %s.\n", argv[3]);
+
+  info = vpx_video_reader_get_info(reader);
+
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
+    die("Unknown input codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
+
+  if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+    die_codec(&codec, "Failed to initialize decoder.");
+
+  while (vpx_video_reader_read_frame(reader)) {
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = NULL;
+    size_t frame_size = 0;
+    int skip;
+    const unsigned char *frame = vpx_video_reader_get_frame(reader,
+                                                            &frame_size);
+    if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
+      die_codec(&codec, "Failed to decode frame.");
+
+    ++frame_cnt;
+
+    skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
+           (!is_range && m - (frame_cnt - 1) % m <= n);
+
+    if (!skip) {
+      putc('.', stdout);
+
+      while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL)
+        vpx_img_write(img, outfile);
+    } else {
+      putc('X', stdout);
+    }
+
+    fflush(stdout);
+  }
+
+  printf("Processed %d frames.\n", frame_cnt);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+         info->frame_width, info->frame_height, argv[2]);
+
+  vpx_video_reader_close(reader);
+  fclose(outfile);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/postproc.c b/src/third_party/libvpx/examples/postproc.c
new file mode 100644
index 0000000..a8ac208
--- /dev/null
+++ b/src/third_party/libvpx/examples/postproc.c
@@ -0,0 +1,138 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+// Postprocessing Decoder
+// ======================
+//
+// This example adds postprocessing to the simple decoder loop.
+//
+// Initializing Postprocessing
+// ---------------------------
+// You must inform the codec that you might request postprocessing at
+// initialization time. This is done by passing the VPX_CODEC_USE_POSTPROC
+// flag to `vpx_codec_dec_init`. If the codec does not support
+// postprocessing, this call will return VPX_CODEC_INCAPABLE. For
+// demonstration purposes, we also fall back to default initialization if
+// the codec does not provide support.
+//
+// Using Adaptive Postprocessing
+// -----------------------------
+// VP6 provides "adaptive postprocessing." It will automatically select the
+// best postprocessing filter on a frame by frame basis based on the amount
+// of time remaining before the user's specified deadline expires. The
+// special value 0 indicates that the codec should take as long as
+// necessary to provide the best quality frame. This example gives the
+// codec 15ms (15000us) to return a frame. Remember that this is a soft
+// deadline, and the codec may exceed it doing its regular processing. In
+// these cases, no additional postprocessing will be done.
+//
+// Codec Specific Postprocessing Controls
+// --------------------------------------
+// Some codecs provide fine grained controls over their built-in
+// postprocessors. VP8 is one example. The following sample code toggles
+// postprocessing on and off every 15 frames.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
+#include "../tools_common.h"
+#include "../video_reader.h"
+#include "./vpx_config.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
+  exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+  int frame_cnt = 0;
+  FILE *outfile = NULL;
+  vpx_codec_ctx_t codec;
+  vpx_codec_err_t res;
+  VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
+  const VpxVideoInfo *info = NULL;
+
+  exec_name = argv[0];
+
+  if (argc != 3)
+    die("Invalid number of arguments.");
+
+  reader = vpx_video_reader_open(argv[1]);
+  if (!reader)
+    die("Failed to open %s for reading.", argv[1]);
+
+  if (!(outfile = fopen(argv[2], "wb")))
+    die("Failed to open %s for writing", argv[2]);
+
+  info = vpx_video_reader_get_info(reader);
+
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
+    die("Unknown input codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
+
+  res = vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL,
+                           VPX_CODEC_USE_POSTPROC);
+  if (res == VPX_CODEC_INCAPABLE)
+    die_codec(&codec, "Postproc not supported by this decoder.");
+
+  if (res)
+    die_codec(&codec, "Failed to initialize decoder.");
+
+  while (vpx_video_reader_read_frame(reader)) {
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = NULL;
+    size_t frame_size = 0;
+    const unsigned char *frame = vpx_video_reader_get_frame(reader,
+                                                            &frame_size);
+
+    ++frame_cnt;
+
+    if (frame_cnt % 30 == 1) {
+      vp8_postproc_cfg_t pp = {0, 0, 0};
+
+    if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+      die_codec(&codec, "Failed to turn off postproc.");
+    } else if (frame_cnt % 30 == 16) {
+      vp8_postproc_cfg_t pp = {VP8_DEBLOCK | VP8_DEMACROBLOCK | VP8_MFQE,
+                               4, 0};
+      if (vpx_codec_control(&codec, VP8_SET_POSTPROC, &pp))
+        die_codec(&codec, "Failed to turn on postproc.");
+    };
+
+    // Decode the frame with 15ms deadline
+    if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 15000))
+      die_codec(&codec, "Failed to decode frame");
+
+    while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+      vpx_img_write(img, outfile);
+    }
+  }
+
+  printf("Processed %d frames.\n", frame_cnt);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec");
+
+  printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+         info->frame_width, info->frame_height, argv[2]);
+
+  vpx_video_reader_close(reader);
+
+  fclose(outfile);
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/resize_util.c b/src/third_party/libvpx/examples/resize_util.c
new file mode 100644
index 0000000..e6fdd5b
--- /dev/null
+++ b/src/third_party/libvpx/examples/resize_util.c
@@ -0,0 +1,130 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 <assert.h>
+#include <limits.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../tools_common.h"
+#include "../vp9/encoder/vp9_resize.h"
+
+static const char *exec_name = NULL;
+
+static void usage() {
+  printf("Usage:\n");
+  printf("%s <input_yuv> <width>x<height> <target_width>x<target_height> ",
+         exec_name);
+  printf("<output_yuv> [<frames>]\n");
+}
+
+void usage_exit(void) {
+  usage();
+  exit(EXIT_FAILURE);
+}
+
+static int parse_dim(char *v, int *width, int *height) {
+  char *x = strchr(v, 'x');
+  if (x == NULL)
+    x = strchr(v, 'X');
+  if (x == NULL)
+    return 0;
+  *width = atoi(v);
+  *height = atoi(&x[1]);
+  if (*width <= 0 || *height <= 0)
+    return 0;
+  else
+    return 1;
+}
+
+int main(int argc, char *argv[]) {
+  char *fin, *fout;
+  FILE *fpin, *fpout;
+  uint8_t *inbuf, *outbuf;
+  uint8_t *inbuf_u, *outbuf_u;
+  uint8_t *inbuf_v, *outbuf_v;
+  int f, frames;
+  int width, height, target_width, target_height;
+
+  exec_name = argv[0];
+
+  if (argc < 5) {
+    printf("Incorrect parameters:\n");
+    usage();
+    return 1;
+  }
+
+  fin = argv[1];
+  fout = argv[4];
+  if (!parse_dim(argv[2], &width, &height)) {
+    printf("Incorrect parameters: %s\n", argv[2]);
+    usage();
+    return 1;
+  }
+  if (!parse_dim(argv[3], &target_width, &target_height)) {
+    printf("Incorrect parameters: %s\n", argv[3]);
+    usage();
+    return 1;
+  }
+
+  fpin = fopen(fin, "rb");
+  if (fpin == NULL) {
+    printf("Can't open file %s to read\n", fin);
+    usage();
+    return 1;
+  }
+  fpout = fopen(fout, "wb");
+  if (fpout == NULL) {
+    printf("Can't open file %s to write\n", fout);
+    usage();
+    return 1;
+  }
+  if (argc >= 6)
+    frames = atoi(argv[5]);
+  else
+    frames = INT_MAX;
+
+  printf("Input size:  %dx%d\n",
+         width, height);
+  printf("Target size: %dx%d, Frames: ",
+         target_width, target_height);
+  if (frames == INT_MAX)
+    printf("All\n");
+  else
+    printf("%d\n", frames);
+
+  inbuf = (uint8_t*)malloc(width * height * 3 / 2);
+  outbuf = (uint8_t*)malloc(target_width * target_height * 3 / 2);
+  inbuf_u = inbuf + width * height;
+  inbuf_v = inbuf_u + width * height / 4;
+  outbuf_u = outbuf + target_width * target_height;
+  outbuf_v = outbuf_u + target_width * target_height / 4;
+  f = 0;
+  while (f < frames) {
+    if (fread(inbuf, width * height * 3 / 2, 1, fpin) != 1)
+      break;
+    vp9_resize_frame420(inbuf, width, inbuf_u, inbuf_v, width / 2,
+                        height, width,
+                        outbuf, target_width, outbuf_u, outbuf_v,
+                        target_width / 2,
+                        target_height, target_width);
+    fwrite(outbuf, target_width * target_height * 3 / 2, 1, fpout);
+    f++;
+  }
+  printf("%d frames processed\n", f);
+  fclose(fpin);
+  fclose(fpout);
+
+  free(inbuf);
+  free(outbuf);
+  return 0;
+}
diff --git a/src/third_party/libvpx/examples/set_maps.c b/src/third_party/libvpx/examples/set_maps.c
new file mode 100644
index 0000000..1dc3ac0
--- /dev/null
+++ b/src/third_party/libvpx/examples/set_maps.c
@@ -0,0 +1,255 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+
+// VP8 Set Active and ROI Maps
+// ===========================
+//
+// This is an example demonstrating how to control the VP8 encoder's
+// ROI and Active maps.
+//
+// ROI (Reigon of Interest) maps are a way for the application to assign
+// each macroblock in the image to a region, and then set quantizer and
+// filtering parameters on that image.
+//
+// Active maps are a way for the application to specify on a
+// macroblock-by-macroblock basis whether there is any activity in that
+// macroblock.
+//
+//
+// Configuration
+// -------------
+// An ROI map is set on frame 22. If the width of the image in macroblocks
+// is evenly divisble by 4, then the output will appear to have distinct
+// columns, where the quantizer, loopfilter, and static threshold differ
+// from column to column.
+//
+// An active map is set on frame 33. If the width of the image in macroblocks
+// is evenly divisble by 4, then the output will appear to have distinct
+// columns, where one column will have motion and the next will not.
+//
+// The active map is cleared on frame 44.
+//
+// Observing The Effects
+// ---------------------
+// Use the `simple_decoder` example to decode this sample, and observe
+// the change in the image at frames 22, 33, and 44.
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <codec> <width> <height> <infile> <outfile>\n",
+          exec_name);
+  exit(EXIT_FAILURE);
+}
+
+static void set_roi_map(const vpx_codec_enc_cfg_t *cfg,
+                        vpx_codec_ctx_t *codec) {
+  unsigned int i;
+  vpx_roi_map_t roi;
+  memset(&roi, 0, sizeof(roi));
+
+  roi.rows = (cfg->g_h + 15) / 16;
+  roi.cols = (cfg->g_w + 15) / 16;
+
+  roi.delta_q[0] = 0;
+  roi.delta_q[1] = -2;
+  roi.delta_q[2] = -4;
+  roi.delta_q[3] = -6;
+
+  roi.delta_lf[0] = 0;
+  roi.delta_lf[1] = 1;
+  roi.delta_lf[2] = 2;
+  roi.delta_lf[3] = 3;
+
+  roi.static_threshold[0] = 1500;
+  roi.static_threshold[1] = 1000;
+  roi.static_threshold[2] = 500;
+  roi.static_threshold[3] = 0;
+
+  roi.roi_map = (uint8_t *)malloc(roi.rows * roi.cols);
+  for (i = 0; i < roi.rows * roi.cols; ++i)
+    roi.roi_map[i] = i % 4;
+
+  if (vpx_codec_control(codec, VP8E_SET_ROI_MAP, &roi))
+    die_codec(codec, "Failed to set ROI map");
+
+  free(roi.roi_map);
+}
+
+static void set_active_map(const vpx_codec_enc_cfg_t *cfg,
+                           vpx_codec_ctx_t *codec) {
+  unsigned int i;
+  vpx_active_map_t map = {0, 0, 0};
+
+  map.rows = (cfg->g_h + 15) / 16;
+  map.cols = (cfg->g_w + 15) / 16;
+
+  map.active_map = (uint8_t *)malloc(map.rows * map.cols);
+  for (i = 0; i < map.rows * map.cols; ++i)
+    map.active_map[i] = i % 2;
+
+  if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
+    die_codec(codec, "Failed to set active map");
+
+  free(map.active_map);
+}
+
+static void unset_active_map(const vpx_codec_enc_cfg_t *cfg,
+                             vpx_codec_ctx_t *codec) {
+  vpx_active_map_t map = {0, 0, 0};
+
+  map.rows = (cfg->g_h + 15) / 16;
+  map.cols = (cfg->g_w + 15) / 16;
+  map.active_map = NULL;
+
+  if (vpx_codec_control(codec, VP8E_SET_ACTIVEMAP, &map))
+    die_codec(codec, "Failed to set active map");
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec,
+                        vpx_image_t *img,
+                        int frame_index,
+                        VpxVideoWriter *writer) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0,
+                                               VPX_DL_GOOD_QUALITY);
+  if (res != VPX_CODEC_OK)
+    die_codec(codec, "Failed to encode frame");
+
+  while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
+    got_pkts = 1;
+
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+      if (!vpx_video_writer_write_frame(writer,
+                                        pkt->data.frame.buf,
+                                        pkt->data.frame.sz,
+                                        pkt->data.frame.pts)) {
+        die_codec(codec, "Failed to write compressed frame");
+      }
+
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
+
+  return got_pkts;
+}
+
+int main(int argc, char **argv) {
+  FILE *infile = NULL;
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  int frame_count = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  VpxVideoInfo info;
+  VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
+  const int fps = 2;        // TODO(dkovalev) add command line argument
+  const double bits_per_pixel_per_frame = 0.067;
+
+  exec_name = argv[0];
+  if (argc != 6)
+    die("Invalid number of arguments");
+
+  memset(&info, 0, sizeof(info));
+
+  encoder = get_vpx_encoder_by_name(argv[1]);
+  if (encoder == NULL) {
+    die("Unsupported codec.");
+  }
+  assert(encoder != NULL);
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(argv[2], NULL, 0);
+  info.frame_height = strtol(argv[3], NULL, 0);
+  info.time_base.numerator = 1;
+  info.time_base.denominator = fps;
+
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image.");
+  }
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = info.frame_width;
+  cfg.g_h = info.frame_height;
+  cfg.g_timebase.num = info.time_base.numerator;
+  cfg.g_timebase.den = info.time_base.denominator;
+  cfg.rc_target_bitrate = (unsigned int)(bits_per_pixel_per_frame * cfg.g_w *
+                                         cfg.g_h * fps / 1000);
+  cfg.g_lag_in_frames = 0;
+
+  writer = vpx_video_writer_open(argv[5], kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing.", argv[5]);
+
+  if (!(infile = fopen(argv[4], "rb")))
+    die("Failed to open %s for reading.", argv[4]);
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  // Encode frames.
+  while (vpx_img_read(&raw, infile)) {
+    ++frame_count;
+
+    if (frame_count == 22 && encoder->fourcc == VP8_FOURCC) {
+      set_roi_map(&cfg, &codec);
+    } else if (frame_count == 33) {
+      set_active_map(&cfg, &codec);
+    } else if (frame_count == 44) {
+      unset_active_map(&cfg, &codec);
+    }
+
+    encode_frame(&codec, &raw, frame_count, writer);
+  }
+
+  // Flush encoder.
+  while (encode_frame(&codec, NULL, -1, writer)) {}
+
+  printf("\n");
+  fclose(infile);
+  printf("Processed %d frames.\n", frame_count);
+
+  vpx_img_free(&raw);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_writer_close(writer);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/simple_decoder.c b/src/third_party/libvpx/examples/simple_decoder.c
new file mode 100644
index 0000000..8ccc810
--- /dev/null
+++ b/src/third_party/libvpx/examples/simple_decoder.c
@@ -0,0 +1,154 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+
+// Simple Decoder
+// ==============
+//
+// This is an example of a simple decoder loop. It takes an input file
+// containing the compressed data (in IVF format), passes it through the
+// decoder, and writes the decompressed frames to disk. Other decoder
+// examples build upon this one.
+//
+// The details of the IVF format have been elided from this example for
+// simplicity of presentation, as IVF files will not generally be used by
+// your application. In general, an IVF file consists of a file header,
+// followed by a variable number of frames. Each frame consists of a frame
+// header followed by a variable length payload. The length of the payload
+// is specified in the first four bytes of the frame header. The payload is
+// the raw compressed data.
+//
+// Standard Includes
+// -----------------
+// For decoders, you only have to include `vpx_decoder.h` and then any
+// header files for the specific codecs you use. In this case, we're using
+// vp8.
+//
+// Initializing The Codec
+// ----------------------
+// The libvpx decoder is initialized by the call to vpx_codec_dec_init().
+// Determining the codec interface to use is handled by VpxVideoReader and the
+// functions prefixed with vpx_video_reader_. Discussion of those functions is
+// beyond the scope of this example, but the main gist is to open the input file
+// and parse just enough of it to determine if it's a VPx file and which VPx
+// codec is contained within the file.
+// Note the NULL pointer passed to vpx_codec_dec_init(). We do that in this
+// example because we want the algorithm to determine the stream configuration
+// (width/height) and allocate memory automatically.
+//
+// Decoding A Frame
+// ----------------
+// Once the frame has been read into memory, it is decoded using the
+// `vpx_codec_decode` function. The call takes a pointer to the data
+// (`frame`) and the length of the data (`frame_size`). No application data
+// is associated with the frame in this example, so the `user_priv`
+// parameter is NULL. The `deadline` parameter is left at zero for this
+// example. This parameter is generally only used when doing adaptive post
+// processing.
+//
+// Codecs may produce a variable number of output frames for every call to
+// `vpx_codec_decode`. These frames are retrieved by the
+// `vpx_codec_get_frame` iterator function. The iterator variable `iter` is
+// initialized to NULL each time `vpx_codec_decode` is called.
+// `vpx_codec_get_frame` is called in a loop, returning a pointer to a
+// decoded image or NULL to indicate the end of list.
+//
+// Processing The Decoded Data
+// ---------------------------
+// In this example, we simply write the encoded data to disk. It is
+// important to honor the image's `stride` values.
+//
+// Cleanup
+// -------
+// The `vpx_codec_destroy` call frees any memory allocated by the codec.
+//
+// Error Handling
+// --------------
+// This example does not special case any error return codes. If there was
+// an error, a descriptive message is printed and the program exits. With
+// few exceptions, vpx_codec functions return an enumerated error status,
+// with the value `0` indicating success.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vpx_decoder.h"
+
+#include "../tools_common.h"
+#include "../video_reader.h"
+#include "./vpx_config.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
+  exit(EXIT_FAILURE);
+}
+
+int main(int argc, char **argv) {
+  int frame_cnt = 0;
+  FILE *outfile = NULL;
+  vpx_codec_ctx_t codec;
+  VpxVideoReader *reader = NULL;
+  const VpxInterface *decoder = NULL;
+  const VpxVideoInfo *info = NULL;
+
+  exec_name = argv[0];
+
+  if (argc != 3)
+    die("Invalid number of arguments.");
+
+  reader = vpx_video_reader_open(argv[1]);
+  if (!reader)
+    die("Failed to open %s for reading.", argv[1]);
+
+  if (!(outfile = fopen(argv[2], "wb")))
+    die("Failed to open %s for writing.", argv[2]);
+
+  info = vpx_video_reader_get_info(reader);
+
+  decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
+  if (!decoder)
+    die("Unknown input codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
+
+  if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
+    die_codec(&codec, "Failed to initialize decoder.");
+
+  while (vpx_video_reader_read_frame(reader)) {
+    vpx_codec_iter_t iter = NULL;
+    vpx_image_t *img = NULL;
+    size_t frame_size = 0;
+    const unsigned char *frame = vpx_video_reader_get_frame(reader,
+                                                            &frame_size);
+    if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
+      die_codec(&codec, "Failed to decode frame.");
+
+    while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
+      vpx_img_write(img, outfile);
+      ++frame_cnt;
+    }
+  }
+
+  printf("Processed %d frames.\n", frame_cnt);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec");
+
+  printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
+         info->frame_width, info->frame_height, argv[2]);
+
+  vpx_video_reader_close(reader);
+
+  fclose(outfile);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/simple_encoder.c b/src/third_party/libvpx/examples/simple_encoder.c
new file mode 100644
index 0000000..64f0a01
--- /dev/null
+++ b/src/third_party/libvpx/examples/simple_encoder.c
@@ -0,0 +1,260 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+// Simple Encoder
+// ==============
+//
+// This is an example of a simple encoder loop. It takes an input file in
+// YV12 format, passes it through the encoder, and writes the compressed
+// frames to disk in IVF format. Other decoder examples build upon this
+// one.
+//
+// The details of the IVF format have been elided from this example for
+// simplicity of presentation, as IVF files will not generally be used by
+// your application. In general, an IVF file consists of a file header,
+// followed by a variable number of frames. Each frame consists of a frame
+// header followed by a variable length payload. The length of the payload
+// is specified in the first four bytes of the frame header. The payload is
+// the raw compressed data.
+//
+// Standard Includes
+// -----------------
+// For encoders, you only have to include `vpx_encoder.h` and then any
+// header files for the specific codecs you use. In this case, we're using
+// vp8.
+//
+// Getting The Default Configuration
+// ---------------------------------
+// Encoders have the notion of "usage profiles." For example, an encoder
+// may want to publish default configurations for both a video
+// conferencing application and a best quality offline encoder. These
+// obviously have very different default settings. Consult the
+// documentation for your codec to see if it provides any default
+// configurations. All codecs provide a default configuration, number 0,
+// which is valid for material in the vacinity of QCIF/QVGA.
+//
+// Updating The Configuration
+// ---------------------------------
+// Almost all applications will want to update the default configuration
+// with settings specific to their usage. Here we set the width and height
+// of the video file to that specified on the command line. We also scale
+// the default bitrate based on the ratio between the default resolution
+// and the resolution specified on the command line.
+//
+// Initializing The Codec
+// ----------------------
+// The encoder is initialized by the following code.
+//
+// Encoding A Frame
+// ----------------
+// The frame is read as a continuous block (size width * height * 3 / 2)
+// from the input file. If a frame was read (the input file has not hit
+// EOF) then the frame is passed to the encoder. Otherwise, a NULL
+// is passed, indicating the End-Of-Stream condition to the encoder. The
+// `frame_cnt` is reused as the presentation time stamp (PTS) and each
+// frame is shown for one frame-time in duration. The flags parameter is
+// unused in this example. The deadline is set to VPX_DL_REALTIME to
+// make the example run as quickly as possible.
+
+// Forced Keyframes
+// ----------------
+// Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
+// flags passed to `vpx_codec_control()`. In this example, we force a
+// keyframe every <keyframe-interval> frames. Note, the output stream can
+// contain additional keyframes beyond those that have been forced using the
+// VPX_EFLAG_FORCE_KF flag because of automatic keyframe placement by the
+// encoder.
+//
+// Processing The Encoded Data
+// ---------------------------
+// Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data
+// for this frame. We write a IVF frame header, followed by the raw data.
+//
+// Cleanup
+// -------
+// The `vpx_codec_destroy` call frees any memory allocated by the codec.
+//
+// Error Handling
+// --------------
+// This example does not special case any error return codes. If there was
+// an error, a descriptive message is printed and the program exits. With
+// few exeptions, vpx_codec functions return an enumerated error status,
+// with the value `0` indicating success.
+//
+// Error Resiliency Features
+// -------------------------
+// Error resiliency is controlled by the g_error_resilient member of the
+// configuration structure. Use the `decode_with_drops` example to decode with
+// frames 5-10 dropped. Compare the output for a file encoded with this example
+// versus one encoded with the `simple_encoder` example.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vpx_encoder.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr,
+          "Usage: %s <codec> <width> <height> <infile> <outfile> "
+              "<keyframe-interval> <error-resilient> <frames to encode>\n"
+              "See comments in simple_encoder.c for more information.\n",
+          exec_name);
+  exit(EXIT_FAILURE);
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec,
+                        vpx_image_t *img,
+                        int frame_index,
+                        int flags,
+                        VpxVideoWriter *writer) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1,
+                                               flags, VPX_DL_GOOD_QUALITY);
+  if (res != VPX_CODEC_OK)
+    die_codec(codec, "Failed to encode frame");
+
+  while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
+    got_pkts = 1;
+
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+      if (!vpx_video_writer_write_frame(writer,
+                                        pkt->data.frame.buf,
+                                        pkt->data.frame.sz,
+                                        pkt->data.frame.pts)) {
+        die_codec(codec, "Failed to write compressed frame");
+      }
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
+
+  return got_pkts;
+}
+
+// TODO(tomfinegan): Improve command line parsing and add args for bitrate/fps.
+int main(int argc, char **argv) {
+  FILE *infile = NULL;
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  int frame_count = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  VpxVideoInfo info = {0};
+  VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
+  const int fps = 30;
+  const int bitrate = 200;
+  int keyframe_interval = 0;
+  int max_frames = 0;
+  int frames_encoded = 0;
+  const char *codec_arg = NULL;
+  const char *width_arg = NULL;
+  const char *height_arg = NULL;
+  const char *infile_arg = NULL;
+  const char *outfile_arg = NULL;
+  const char *keyframe_interval_arg = NULL;
+
+  exec_name = argv[0];
+
+  if (argc != 9)
+    die("Invalid number of arguments");
+
+  codec_arg = argv[1];
+  width_arg = argv[2];
+  height_arg = argv[3];
+  infile_arg = argv[4];
+  outfile_arg = argv[5];
+  keyframe_interval_arg = argv[6];
+  max_frames = strtol(argv[8], NULL, 0);
+
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+     die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(width_arg, NULL, 0);
+  info.frame_height = strtol(height_arg, NULL, 0);
+  info.time_base.numerator = 1;
+  info.time_base.denominator = fps;
+
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image.");
+  }
+
+  keyframe_interval = strtol(keyframe_interval_arg, NULL, 0);
+  if (keyframe_interval < 0)
+    die("Invalid keyframe interval value.");
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = info.frame_width;
+  cfg.g_h = info.frame_height;
+  cfg.g_timebase.num = info.time_base.numerator;
+  cfg.g_timebase.den = info.time_base.denominator;
+  cfg.rc_target_bitrate = bitrate;
+  cfg.g_error_resilient = strtol(argv[7], NULL, 0);
+
+  writer = vpx_video_writer_open(outfile_arg, kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing.", outfile_arg);
+
+  if (!(infile = fopen(infile_arg, "rb")))
+    die("Failed to open %s for reading.", infile_arg);
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  // Encode frames.
+  while (vpx_img_read(&raw, infile)) {
+    int flags = 0;
+    if (keyframe_interval > 0 && frame_count % keyframe_interval == 0)
+      flags |= VPX_EFLAG_FORCE_KF;
+    encode_frame(&codec, &raw, frame_count++, flags, writer);
+    frames_encoded++;
+    if (max_frames > 0 && frames_encoded >= max_frames)
+      break;
+  }
+
+  // Flush encoder.
+  while (encode_frame(&codec, NULL, -1, 0, writer)) {};
+
+  printf("\n");
+  fclose(infile);
+  printf("Processed %d frames.\n", frame_count);
+
+  vpx_img_free(&raw);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_writer_close(writer);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/twopass_encoder.c b/src/third_party/libvpx/examples/twopass_encoder.c
new file mode 100644
index 0000000..15a6617
--- /dev/null
+++ b/src/third_party/libvpx/examples/twopass_encoder.c
@@ -0,0 +1,277 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+// Two Pass Encoder
+// ================
+//
+// This is an example of a two pass encoder loop. It takes an input file in
+// YV12 format, passes it through the encoder twice, and writes the compressed
+// frames to disk in IVF format. It builds upon the simple_encoder example.
+//
+// Twopass Variables
+// -----------------
+// Twopass mode needs to track the current pass number and the buffer of
+// statistics packets.
+//
+// Updating The Configuration
+// ---------------------------------
+// In two pass mode, the configuration has to be updated on each pass. The
+// statistics buffer is passed on the last pass.
+//
+// Encoding A Frame
+// ----------------
+// Encoding a frame in two pass mode is identical to the simple encoder
+// example. To increase the quality while sacrificing encoding speed,
+// VPX_DL_BEST_QUALITY can be used in place of VPX_DL_GOOD_QUALITY.
+//
+// Processing Statistics Packets
+// -----------------------------
+// Each packet of type `VPX_CODEC_CX_FRAME_PKT` contains the encoded data
+// for this frame. We write a IVF frame header, followed by the raw data.
+//
+//
+// Pass Progress Reporting
+// -----------------------------
+// It's sometimes helpful to see when each pass completes.
+//
+//
+// Clean-up
+// -----------------------------
+// Destruction of the encoder instance must be done on each pass. The
+// raw image should be destroyed at the end as usual.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vpx_encoder.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr,
+          "Usage: %s <codec> <width> <height> <infile> <outfile> "
+              "<frame limit>\n",
+          exec_name);
+  exit(EXIT_FAILURE);
+}
+
+static int get_frame_stats(vpx_codec_ctx_t *ctx,
+                           const vpx_image_t *img,
+                           vpx_codec_pts_t pts,
+                           unsigned int duration,
+                           vpx_enc_frame_flags_t flags,
+                           unsigned int deadline,
+                           vpx_fixed_buf_t *stats) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
+                                               deadline);
+  if (res != VPX_CODEC_OK)
+    die_codec(ctx, "Failed to get frame stats.");
+
+  while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
+    got_pkts = 1;
+
+    if (pkt->kind == VPX_CODEC_STATS_PKT) {
+      const uint8_t *const pkt_buf = pkt->data.twopass_stats.buf;
+      const size_t pkt_size = pkt->data.twopass_stats.sz;
+      stats->buf = realloc(stats->buf, stats->sz + pkt_size);
+      memcpy((uint8_t *)stats->buf + stats->sz, pkt_buf, pkt_size);
+      stats->sz += pkt_size;
+    }
+  }
+
+  return got_pkts;
+}
+
+static int encode_frame(vpx_codec_ctx_t *ctx,
+                        const vpx_image_t *img,
+                        vpx_codec_pts_t pts,
+                        unsigned int duration,
+                        vpx_enc_frame_flags_t flags,
+                        unsigned int deadline,
+                        VpxVideoWriter *writer) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(ctx, img, pts, duration, flags,
+                                               deadline);
+  if (res != VPX_CODEC_OK)
+    die_codec(ctx, "Failed to encode frame.");
+
+  while ((pkt = vpx_codec_get_cx_data(ctx, &iter)) != NULL) {
+    got_pkts = 1;
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+
+      if (!vpx_video_writer_write_frame(writer, pkt->data.frame.buf,
+                                                pkt->data.frame.sz,
+                                                pkt->data.frame.pts))
+        die_codec(ctx, "Failed to write compressed frame.");
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
+
+  return got_pkts;
+}
+
+static vpx_fixed_buf_t pass0(vpx_image_t *raw,
+                             FILE *infile,
+                             const VpxInterface *encoder,
+                             const vpx_codec_enc_cfg_t *cfg,
+                             int max_frames) {
+  vpx_codec_ctx_t codec;
+  int frame_count = 0;
+  vpx_fixed_buf_t stats = {NULL, 0};
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  // Calculate frame statistics.
+  while (vpx_img_read(raw, infile)) {
+    ++frame_count;
+    get_frame_stats(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY,
+                    &stats);
+    if (max_frames > 0 && frame_count >= max_frames)
+      break;
+  }
+
+  // Flush encoder.
+  while (get_frame_stats(&codec, NULL, frame_count, 1, 0,
+                         VPX_DL_GOOD_QUALITY, &stats)) {}
+
+  printf("Pass 0 complete. Processed %d frames.\n", frame_count);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  return stats;
+}
+
+static void pass1(vpx_image_t *raw,
+                  FILE *infile,
+                  const char *outfile_name,
+                  const VpxInterface *encoder,
+                  const vpx_codec_enc_cfg_t *cfg,
+                  int max_frames) {
+  VpxVideoInfo info = {
+    encoder->fourcc,
+    cfg->g_w,
+    cfg->g_h,
+    {cfg->g_timebase.num, cfg->g_timebase.den}
+  };
+  VpxVideoWriter *writer = NULL;
+  vpx_codec_ctx_t codec;
+  int frame_count = 0;
+
+  writer = vpx_video_writer_open(outfile_name, kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing", outfile_name);
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  // Encode frames.
+  while (vpx_img_read(raw, infile)) {
+    ++frame_count;
+    encode_frame(&codec, raw, frame_count, 1, 0, VPX_DL_GOOD_QUALITY, writer);
+
+    if (max_frames > 0 && frame_count >= max_frames)
+      break;
+  }
+
+  // Flush encoder.
+  while (encode_frame(&codec, NULL, -1, 1, 0, VPX_DL_GOOD_QUALITY, writer)) {}
+
+  printf("\n");
+
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_writer_close(writer);
+
+  printf("Pass 1 complete. Processed %d frames.\n", frame_count);
+}
+
+int main(int argc, char **argv) {
+  FILE *infile = NULL;
+  int w, h;
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  vpx_fixed_buf_t stats;
+
+  const VpxInterface *encoder = NULL;
+  const int fps = 30;        // TODO(dkovalev) add command line argument
+  const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+  const char *const codec_arg = argv[1];
+  const char *const width_arg = argv[2];
+  const char *const height_arg = argv[3];
+  const char *const infile_arg = argv[4];
+  const char *const outfile_arg = argv[5];
+  int max_frames = 0;
+  exec_name = argv[0];
+
+  if (argc != 7)
+    die("Invalid number of arguments.");
+
+  max_frames = strtol(argv[6], NULL, 0);
+
+  encoder = get_vpx_encoder_by_name(codec_arg);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  w = strtol(width_arg, NULL, 0);
+  h = strtol(height_arg, NULL, 0);
+
+  if (w  <= 0 || h <= 0 || (w % 2) != 0 || (h  % 2) != 0)
+    die("Invalid frame size: %dx%d", w, h);
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, w, h, 1))
+    die("Failed to allocate image", w, h);
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  // Configuration
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = w;
+  cfg.g_h = h;
+  cfg.g_timebase.num = 1;
+  cfg.g_timebase.den = fps;
+  cfg.rc_target_bitrate = bitrate;
+
+  if (!(infile = fopen(infile_arg, "rb")))
+    die("Failed to open %s for reading", infile_arg);
+
+  // Pass 0
+  cfg.g_pass = VPX_RC_FIRST_PASS;
+  stats = pass0(&raw, infile, encoder, &cfg, max_frames);
+
+  // Pass 1
+  rewind(infile);
+  cfg.g_pass = VPX_RC_LAST_PASS;
+  cfg.rc_twopass_stats_in = stats;
+  pass1(&raw, infile, outfile_arg, encoder, &cfg, max_frames);
+  free(stats.buf);
+
+  vpx_img_free(&raw);
+  fclose(infile);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c b/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c
new file mode 100644
index 0000000..fc775ef
--- /dev/null
+++ b/src/third_party/libvpx/examples/vp8_multi_resolution_encoder.c
@@ -0,0 +1,731 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+/*
+ * This is an example demonstrating multi-resolution encoding in VP8.
+ * High-resolution input video is down-sampled to lower-resolutions. The
+ * encoder then encodes the video and outputs multiple bitstreams with
+ * different resolutions.
+ *
+ * This test also allows for settings temporal layers for each spatial layer.
+ * Different number of temporal layers per spatial stream may be used.
+ * Currently up to 3 temporal layers per spatial stream (encoder) are supported
+ * in this test.
+ */
+
+#include "./vpx_config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "vpx_ports/vpx_timer.h"
+#include "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+#include "vpx_ports/mem_ops.h"
+#include "../tools_common.h"
+#define interface (vpx_codec_vp8_cx())
+#define fourcc    0x30385056
+
+void usage_exit(void) {
+  exit(EXIT_FAILURE);
+}
+
+/*
+ * The input video frame is downsampled several times to generate a multi-level
+ * hierarchical structure. NUM_ENCODERS is defined as the number of encoding
+ * levels required. For example, if the size of input video is 1280x720,
+ * NUM_ENCODERS is 3, and down-sampling factor is 2, the encoder outputs 3
+ * bitstreams with resolution of 1280x720(level 0), 640x360(level 1), and
+ * 320x180(level 2) respectively.
+ */
+
+/* Number of encoders (spatial resolutions) used in this test. */
+#define NUM_ENCODERS 3
+
+/* Maximum number of temporal layers allowed for this test. */
+#define MAX_NUM_TEMPORAL_LAYERS 3
+
+/* This example uses the scaler function in libyuv. */
+#include "third_party/libyuv/include/libyuv/basic_types.h"
+#include "third_party/libyuv/include/libyuv/scale.h"
+#include "third_party/libyuv/include/libyuv/cpu_id.h"
+
+int (*read_frame_p)(FILE *f, vpx_image_t *img);
+
+static int read_frame(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+
+    to_read = img->w*img->h*3/2;
+    nbytes = fread(img->planes[0], 1, to_read, f);
+    if(nbytes != to_read) {
+        res = 0;
+        if(nbytes > 0)
+            printf("Warning: Read partial frame. Check your width & height!\n");
+    }
+    return res;
+}
+
+static int read_frame_by_row(FILE *f, vpx_image_t *img) {
+    size_t nbytes, to_read;
+    int    res = 1;
+    int plane;
+
+    for (plane = 0; plane < 3; plane++)
+    {
+        unsigned char *ptr;
+        int w = (plane ? (1 + img->d_w) / 2 : img->d_w);
+        int h = (plane ? (1 + img->d_h) / 2 : img->d_h);
+        int r;
+
+        /* Determine the correct plane based on the image format. The for-loop
+         * always counts in Y,U,V order, but this may not match the order of
+         * the data on disk.
+         */
+        switch (plane)
+        {
+        case 1:
+            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12? VPX_PLANE_V : VPX_PLANE_U];
+            break;
+        case 2:
+            ptr = img->planes[img->fmt==VPX_IMG_FMT_YV12?VPX_PLANE_U : VPX_PLANE_V];
+            break;
+        default:
+            ptr = img->planes[plane];
+        }
+
+        for (r = 0; r < h; r++)
+        {
+            to_read = w;
+
+            nbytes = fread(ptr, 1, to_read, f);
+            if(nbytes != to_read) {
+                res = 0;
+                if(nbytes > 0)
+                    printf("Warning: Read partial frame. Check your width & height!\n");
+                break;
+            }
+
+            ptr += img->stride[plane];
+        }
+        if (!res)
+            break;
+    }
+
+    return res;
+}
+
+static void write_ivf_file_header(FILE *outfile,
+                                  const vpx_codec_enc_cfg_t *cfg,
+                                  int frame_cnt) {
+    char header[32];
+
+    if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+        return;
+    header[0] = 'D';
+    header[1] = 'K';
+    header[2] = 'I';
+    header[3] = 'F';
+    mem_put_le16(header+4,  0);                   /* version */
+    mem_put_le16(header+6,  32);                  /* headersize */
+    mem_put_le32(header+8,  fourcc);              /* headersize */
+    mem_put_le16(header+12, cfg->g_w);            /* width */
+    mem_put_le16(header+14, cfg->g_h);            /* height */
+    mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
+    mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
+    mem_put_le32(header+24, frame_cnt);           /* length */
+    mem_put_le32(header+28, 0);                   /* unused */
+
+    (void) fwrite(header, 1, 32, outfile);
+}
+
+static void write_ivf_frame_header(FILE *outfile,
+                                   const vpx_codec_cx_pkt_t *pkt)
+{
+    char             header[12];
+    vpx_codec_pts_t  pts;
+
+    if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+        return;
+
+    pts = pkt->data.frame.pts;
+    mem_put_le32(header, pkt->data.frame.sz);
+    mem_put_le32(header+4, pts&0xFFFFFFFF);
+    mem_put_le32(header+8, pts >> 32);
+
+    (void) fwrite(header, 1, 12, outfile);
+}
+
+/* Temporal scaling parameters */
+/* This sets all the temporal layer parameters given |num_temporal_layers|,
+ * including the target bit allocation across temporal layers. Bit allocation
+ * parameters will be passed in as user parameters in another version.
+ */
+static void set_temporal_layer_pattern(int num_temporal_layers,
+                                       vpx_codec_enc_cfg_t *cfg,
+                                       int bitrate,
+                                       int *layer_flags)
+{
+    assert(num_temporal_layers <= MAX_NUM_TEMPORAL_LAYERS);
+    switch (num_temporal_layers)
+    {
+    case 1:
+    {
+        /* 1-layer */
+        cfg->ts_number_layers     = 1;
+        cfg->ts_periodicity       = 1;
+        cfg->ts_rate_decimator[0] = 1;
+        cfg->ts_layer_id[0] = 0;
+        cfg->ts_target_bitrate[0] = bitrate;
+
+        // Update L only.
+        layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+        break;
+    }
+
+    case 2:
+    {
+        /* 2-layers, with sync point at first frame of layer 1. */
+        cfg->ts_number_layers     = 2;
+        cfg->ts_periodicity       = 2;
+        cfg->ts_rate_decimator[0] = 2;
+        cfg->ts_rate_decimator[1] = 1;
+        cfg->ts_layer_id[0] = 0;
+        cfg->ts_layer_id[1] = 1;
+        // Use 60/40 bit allocation as example.
+        cfg->ts_target_bitrate[0] = 0.6f * bitrate;
+        cfg->ts_target_bitrate[1] = bitrate;
+
+        /* 0=L, 1=GF */
+        // ARF is used as predictor for all frames, and is only updated on
+        // key frame. Sync point every 8 frames.
+
+        // Layer 0: predict from L and ARF, update L and G.
+        layer_flags[0] = VP8_EFLAG_NO_REF_GF |
+                         VP8_EFLAG_NO_UPD_ARF;
+
+        // Layer 1: sync point: predict from L and ARF, and update G.
+        layer_flags[1] = VP8_EFLAG_NO_REF_GF |
+                         VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_UPD_ARF;
+
+        // Layer 0, predict from L and ARF, update L.
+        layer_flags[2] = VP8_EFLAG_NO_REF_GF  |
+                         VP8_EFLAG_NO_UPD_GF  |
+                         VP8_EFLAG_NO_UPD_ARF;
+
+        // Layer 1: predict from L, G and ARF, and update G.
+        layer_flags[3] = VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_UPD_ENTROPY;
+
+        // Layer 0
+        layer_flags[4] = layer_flags[2];
+
+        // Layer 1
+        layer_flags[5] = layer_flags[3];
+
+        // Layer 0
+        layer_flags[6] = layer_flags[4];
+
+        // Layer 1
+        layer_flags[7] = layer_flags[5];
+        break;
+    }
+
+    case 3:
+    default:
+    {
+        // 3-layers structure where ARF is used as predictor for all frames,
+        // and is only updated on key frame.
+        // Sync points for layer 1 and 2 every 8 frames.
+        cfg->ts_number_layers     = 3;
+        cfg->ts_periodicity       = 4;
+        cfg->ts_rate_decimator[0] = 4;
+        cfg->ts_rate_decimator[1] = 2;
+        cfg->ts_rate_decimator[2] = 1;
+        cfg->ts_layer_id[0] = 0;
+        cfg->ts_layer_id[1] = 2;
+        cfg->ts_layer_id[2] = 1;
+        cfg->ts_layer_id[3] = 2;
+        // Use 40/20/40 bit allocation as example.
+        cfg->ts_target_bitrate[0] = 0.4f * bitrate;
+        cfg->ts_target_bitrate[1] = 0.6f * bitrate;
+        cfg->ts_target_bitrate[2] = bitrate;
+
+        /* 0=L, 1=GF, 2=ARF */
+
+        // Layer 0: predict from L and ARF; update L and G.
+        layer_flags[0] =  VP8_EFLAG_NO_UPD_ARF |
+                          VP8_EFLAG_NO_REF_GF;
+
+        // Layer 2: sync point: predict from L and ARF; update none.
+        layer_flags[1] = VP8_EFLAG_NO_REF_GF |
+                         VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_UPD_ENTROPY;
+
+        // Layer 1: sync point: predict from L and ARF; update G.
+        layer_flags[2] = VP8_EFLAG_NO_REF_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST;
+
+        // Layer 2: predict from L, G, ARF; update none.
+        layer_flags[3] = VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST |
+                         VP8_EFLAG_NO_UPD_ENTROPY;
+
+        // Layer 0: predict from L and ARF; update L.
+        layer_flags[4] = VP8_EFLAG_NO_UPD_GF |
+                         VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_REF_GF;
+
+        // Layer 2: predict from L, G, ARF; update none.
+        layer_flags[5] = layer_flags[3];
+
+        // Layer 1: predict from L, G, ARF; update G.
+        layer_flags[6] = VP8_EFLAG_NO_UPD_ARF |
+                         VP8_EFLAG_NO_UPD_LAST;
+
+        // Layer 2: predict from L, G, ARF; update none.
+        layer_flags[7] = layer_flags[3];
+        break;
+    }
+    }
+}
+
+/* The periodicity of the pattern given the number of temporal layers. */
+static int periodicity_to_num_layers[MAX_NUM_TEMPORAL_LAYERS] = {1, 8, 8};
+
+int main(int argc, char **argv)
+{
+    FILE                 *infile, *outfile[NUM_ENCODERS];
+    FILE                 *downsampled_input[NUM_ENCODERS - 1];
+    char                 filename[50];
+    vpx_codec_ctx_t      codec[NUM_ENCODERS];
+    vpx_codec_enc_cfg_t  cfg[NUM_ENCODERS];
+    int                  frame_cnt = 0;
+    vpx_image_t          raw[NUM_ENCODERS];
+    vpx_codec_err_t      res[NUM_ENCODERS];
+
+    int                  i;
+    long                 width;
+    long                 height;
+    int                  length_frame;
+    int                  frame_avail;
+    int                  got_data;
+    int                  flags = 0;
+    int                  layer_id = 0;
+
+    int                  layer_flags[VPX_TS_MAX_PERIODICITY * NUM_ENCODERS]
+                                     = {0};
+    int                  flag_periodicity;
+
+    /*Currently, only realtime mode is supported in multi-resolution encoding.*/
+    int                  arg_deadline = VPX_DL_REALTIME;
+
+    /* Set show_psnr to 1/0 to show/not show PSNR. Choose show_psnr=0 if you
+       don't need to know PSNR, which will skip PSNR calculation and save
+       encoding time. */
+    int                  show_psnr = 0;
+    int                  key_frame_insert = 0;
+    uint64_t             psnr_sse_total[NUM_ENCODERS] = {0};
+    uint64_t             psnr_samples_total[NUM_ENCODERS] = {0};
+    double               psnr_totals[NUM_ENCODERS][4] = {{0,0}};
+    int                  psnr_count[NUM_ENCODERS] = {0};
+
+    int64_t              cx_time = 0;
+
+    /* Set the required target bitrates for each resolution level.
+     * If target bitrate for highest-resolution level is set to 0,
+     * (i.e. target_bitrate[0]=0), we skip encoding at that level.
+     */
+    unsigned int         target_bitrate[NUM_ENCODERS]={1000, 500, 100};
+
+    /* Enter the frame rate of the input video */
+    int                  framerate = 30;
+
+    /* Set down-sampling factor for each resolution level.
+       dsf[0] controls down sampling from level 0 to level 1;
+       dsf[1] controls down sampling from level 1 to level 2;
+       dsf[2] is not used. */
+    vpx_rational_t dsf[NUM_ENCODERS] = {{2, 1}, {2, 1}, {1, 1}};
+
+    /* Set the number of temporal layers for each encoder/resolution level,
+     * starting from highest resoln down to lowest resoln. */
+    unsigned int         num_temporal_layers[NUM_ENCODERS] = {3, 3, 3};
+
+    if(argc!= (7 + 3 * NUM_ENCODERS))
+        die("Usage: %s <width> <height> <frame_rate>  <infile> <outfile(s)> "
+            "<rate_encoder(s)> <temporal_layer(s)> <key_frame_insert> <output psnr?> \n",
+            argv[0]);
+
+    printf("Using %s\n",vpx_codec_iface_name(interface));
+
+    width = strtol(argv[1], NULL, 0);
+    height = strtol(argv[2], NULL, 0);
+    framerate = strtol(argv[3], NULL, 0);
+
+    if(width < 16 || width%2 || height <16 || height%2)
+        die("Invalid resolution: %ldx%ld", width, height);
+
+    /* Open input video file for encoding */
+    if(!(infile = fopen(argv[4], "rb")))
+        die("Failed to open %s for reading", argv[4]);
+
+    /* Open output file for each encoder to output bitstreams */
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        if(!target_bitrate[i])
+        {
+            outfile[i] = NULL;
+            continue;
+        }
+
+        if(!(outfile[i] = fopen(argv[i+5], "wb")))
+            die("Failed to open %s for writing", argv[i+4]);
+    }
+
+    // Bitrates per spatial layer: overwrite default rates above.
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        target_bitrate[i] = strtol(argv[NUM_ENCODERS + 5 + i], NULL, 0);
+    }
+
+    // Temporal layers per spatial layers: overwrite default settings above.
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        num_temporal_layers[i] = strtol(argv[2 * NUM_ENCODERS + 5 + i], NULL, 0);
+        if (num_temporal_layers[i] < 1 || num_temporal_layers[i] > 3)
+          die("Invalid temporal layers: %d, Must be 1, 2, or 3. \n",
+              num_temporal_layers);
+    }
+
+    /* Open file to write out each spatially downsampled input stream. */
+    for (i=0; i< NUM_ENCODERS - 1; i++)
+    {
+       // Highest resoln is encoder 0.
+        if (sprintf(filename,"ds%d.yuv",NUM_ENCODERS - i) < 0)
+        {
+            return EXIT_FAILURE;
+        }
+        downsampled_input[i] = fopen(filename,"wb");
+    }
+
+    key_frame_insert = strtol(argv[3 * NUM_ENCODERS + 5], NULL, 0);
+
+    show_psnr = strtol(argv[3 * NUM_ENCODERS + 6], NULL, 0);
+
+
+    /* Populate default encoder configuration */
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        res[i] = vpx_codec_enc_config_default(interface, &cfg[i], 0);
+        if(res[i]) {
+            printf("Failed to get config: %s\n", vpx_codec_err_to_string(res[i]));
+            return EXIT_FAILURE;
+        }
+    }
+
+    /*
+     * Update the default configuration according to needs of the application.
+     */
+    /* Highest-resolution encoder settings */
+    cfg[0].g_w = width;
+    cfg[0].g_h = height;
+    cfg[0].rc_dropframe_thresh = 0;
+    cfg[0].rc_end_usage = VPX_CBR;
+    cfg[0].rc_resize_allowed = 0;
+    cfg[0].rc_min_quantizer = 2;
+    cfg[0].rc_max_quantizer = 56;
+    cfg[0].rc_undershoot_pct = 100;
+    cfg[0].rc_overshoot_pct = 15;
+    cfg[0].rc_buf_initial_sz = 500;
+    cfg[0].rc_buf_optimal_sz = 600;
+    cfg[0].rc_buf_sz = 1000;
+    cfg[0].g_error_resilient = 1;              /* Enable error resilient mode */
+    cfg[0].g_lag_in_frames   = 0;
+
+    /* Disable automatic keyframe placement */
+    /* Note: These 3 settings are copied to all levels. But, except the lowest
+     * resolution level, all other levels are set to VPX_KF_DISABLED internally.
+     */
+    cfg[0].kf_mode           = VPX_KF_AUTO;
+    cfg[0].kf_min_dist = 3000;
+    cfg[0].kf_max_dist = 3000;
+
+    cfg[0].rc_target_bitrate = target_bitrate[0];       /* Set target bitrate */
+    cfg[0].g_timebase.num = 1;                          /* Set fps */
+    cfg[0].g_timebase.den = framerate;
+
+    /* Other-resolution encoder settings */
+    for (i=1; i< NUM_ENCODERS; i++)
+    {
+        memcpy(&cfg[i], &cfg[0], sizeof(vpx_codec_enc_cfg_t));
+
+        cfg[i].rc_target_bitrate = target_bitrate[i];
+
+        /* Note: Width & height of other-resolution encoders are calculated
+         * from the highest-resolution encoder's size and the corresponding
+         * down_sampling_factor.
+         */
+        {
+            unsigned int iw = cfg[i-1].g_w*dsf[i-1].den + dsf[i-1].num - 1;
+            unsigned int ih = cfg[i-1].g_h*dsf[i-1].den + dsf[i-1].num - 1;
+            cfg[i].g_w = iw/dsf[i-1].num;
+            cfg[i].g_h = ih/dsf[i-1].num;
+        }
+
+        /* Make width & height to be multiplier of 2. */
+        // Should support odd size ???
+        if((cfg[i].g_w)%2)cfg[i].g_w++;
+        if((cfg[i].g_h)%2)cfg[i].g_h++;
+    }
+
+
+    // Set the number of threads per encode/spatial layer.
+    // (1, 1, 1) means no encoder threading.
+    cfg[0].g_threads = 2;
+    cfg[1].g_threads = 1;
+    cfg[2].g_threads = 1;
+
+    /* Allocate image for each encoder */
+    for (i=0; i< NUM_ENCODERS; i++)
+        if(!vpx_img_alloc(&raw[i], VPX_IMG_FMT_I420, cfg[i].g_w, cfg[i].g_h, 32))
+            die("Failed to allocate image", cfg[i].g_w, cfg[i].g_h);
+
+    if (raw[0].stride[VPX_PLANE_Y] == raw[0].d_w)
+        read_frame_p = read_frame;
+    else
+        read_frame_p = read_frame_by_row;
+
+    for (i=0; i< NUM_ENCODERS; i++)
+        if(outfile[i])
+            write_ivf_file_header(outfile[i], &cfg[i], 0);
+
+    /* Temporal layers settings */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        set_temporal_layer_pattern(num_temporal_layers[i],
+                                   &cfg[i],
+                                   cfg[i].rc_target_bitrate,
+                                   &layer_flags[i * VPX_TS_MAX_PERIODICITY]);
+    }
+
+    /* Initialize multi-encoder */
+    if(vpx_codec_enc_init_multi(&codec[0], interface, &cfg[0], NUM_ENCODERS,
+                                (show_psnr ? VPX_CODEC_USE_PSNR : 0), &dsf[0]))
+        die_codec(&codec[0], "Failed to initialize encoder");
+
+    /* The extra encoding configuration parameters can be set as follows. */
+    /* Set encoding speed */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        int speed = -6;
+        /* Lower speed for the lowest resolution. */
+        if (i == NUM_ENCODERS - 1) speed = -4;
+        if(vpx_codec_control(&codec[i], VP8E_SET_CPUUSED, speed))
+            die_codec(&codec[i], "Failed to set cpu_used");
+    }
+
+    /* Set static threshold = 1 for all encoders */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        if(vpx_codec_control(&codec[i], VP8E_SET_STATIC_THRESHOLD, 1))
+            die_codec(&codec[i], "Failed to set static threshold");
+    }
+
+    /* Set NOISE_SENSITIVITY to do TEMPORAL_DENOISING */
+    /* Enable denoising for the highest-resolution encoder. */
+    if(vpx_codec_control(&codec[0], VP8E_SET_NOISE_SENSITIVITY, 1))
+        die_codec(&codec[0], "Failed to set noise_sensitivity");
+    for ( i=1; i< NUM_ENCODERS; i++)
+    {
+        if(vpx_codec_control(&codec[i], VP8E_SET_NOISE_SENSITIVITY, 0))
+            die_codec(&codec[i], "Failed to set noise_sensitivity");
+    }
+
+    /* Set the number of token partitions */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        if(vpx_codec_control(&codec[i], VP8E_SET_TOKEN_PARTITIONS, 1))
+            die_codec(&codec[i], "Failed to set static threshold");
+    }
+
+    /* Set the max intra target bitrate */
+    for ( i=0; i<NUM_ENCODERS; i++)
+    {
+        unsigned int max_intra_size_pct =
+            (int)(((double)cfg[0].rc_buf_optimal_sz * 0.5) * framerate / 10);
+        if(vpx_codec_control(&codec[i], VP8E_SET_MAX_INTRA_BITRATE_PCT,
+                             max_intra_size_pct))
+            die_codec(&codec[i], "Failed to set static threshold");
+       //printf("%d %d \n",i,max_intra_size_pct);
+    }
+
+    frame_avail = 1;
+    got_data = 0;
+
+    while(frame_avail || got_data)
+    {
+        struct vpx_usec_timer timer;
+        vpx_codec_iter_t iter[NUM_ENCODERS]={NULL};
+        const vpx_codec_cx_pkt_t *pkt[NUM_ENCODERS];
+
+        flags = 0;
+        frame_avail = read_frame_p(infile, &raw[0]);
+
+        if(frame_avail)
+        {
+            for ( i=1; i<NUM_ENCODERS; i++)
+            {
+                /*Scale the image down a number of times by downsampling factor*/
+                /* FilterMode 1 or 2 give better psnr than FilterMode 0. */
+                I420Scale(raw[i-1].planes[VPX_PLANE_Y], raw[i-1].stride[VPX_PLANE_Y],
+                          raw[i-1].planes[VPX_PLANE_U], raw[i-1].stride[VPX_PLANE_U],
+                          raw[i-1].planes[VPX_PLANE_V], raw[i-1].stride[VPX_PLANE_V],
+                          raw[i-1].d_w, raw[i-1].d_h,
+                          raw[i].planes[VPX_PLANE_Y], raw[i].stride[VPX_PLANE_Y],
+                          raw[i].planes[VPX_PLANE_U], raw[i].stride[VPX_PLANE_U],
+                          raw[i].planes[VPX_PLANE_V], raw[i].stride[VPX_PLANE_V],
+                          raw[i].d_w, raw[i].d_h, 1);
+                /* Write out down-sampled input. */
+                length_frame = cfg[i].g_w *  cfg[i].g_h *3/2;
+                if (fwrite(raw[i].planes[0], 1, length_frame,
+                           downsampled_input[NUM_ENCODERS - i - 1]) !=
+                               length_frame)
+                {
+                    return EXIT_FAILURE;
+                }
+            }
+        }
+
+        /* Set the flags (reference and update) for all the encoders.*/
+        for ( i=0; i<NUM_ENCODERS; i++)
+        {
+            layer_id = cfg[i].ts_layer_id[frame_cnt % cfg[i].ts_periodicity];
+            flags = 0;
+            flag_periodicity = periodicity_to_num_layers
+                [num_temporal_layers[i] - 1];
+            flags = layer_flags[i * VPX_TS_MAX_PERIODICITY +
+                                frame_cnt % flag_periodicity];
+            // Key frame flag for first frame.
+            if (frame_cnt == 0)
+            {
+                flags |= VPX_EFLAG_FORCE_KF;
+            }
+            if (frame_cnt > 0 && frame_cnt == key_frame_insert)
+            {
+                flags = VPX_EFLAG_FORCE_KF;
+            }
+
+            vpx_codec_control(&codec[i], VP8E_SET_FRAME_FLAGS, flags);
+            vpx_codec_control(&codec[i], VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
+        }
+
+        /* Encode each frame at multi-levels */
+        /* Note the flags must be set to 0 in the encode call if they are set
+           for each frame with the vpx_codec_control(), as done above. */
+        vpx_usec_timer_start(&timer);
+        if(vpx_codec_encode(&codec[0], frame_avail? &raw[0] : NULL,
+            frame_cnt, 1, 0, arg_deadline))
+        {
+            die_codec(&codec[0], "Failed to encode frame");
+        }
+        vpx_usec_timer_mark(&timer);
+        cx_time += vpx_usec_timer_elapsed(&timer);
+
+        for (i=NUM_ENCODERS-1; i>=0 ; i--)
+        {
+            got_data = 0;
+            while( (pkt[i] = vpx_codec_get_cx_data(&codec[i], &iter[i])) )
+            {
+                got_data = 1;
+                switch(pkt[i]->kind) {
+                    case VPX_CODEC_CX_FRAME_PKT:
+                        write_ivf_frame_header(outfile[i], pkt[i]);
+                        (void) fwrite(pkt[i]->data.frame.buf, 1,
+                                      pkt[i]->data.frame.sz, outfile[i]);
+                    break;
+                    case VPX_CODEC_PSNR_PKT:
+                        if (show_psnr)
+                        {
+                            int j;
+
+                            psnr_sse_total[i] += pkt[i]->data.psnr.sse[0];
+                            psnr_samples_total[i] += pkt[i]->data.psnr.samples[0];
+                            for (j = 0; j < 4; j++)
+                            {
+                                psnr_totals[i][j] += pkt[i]->data.psnr.psnr[j];
+                            }
+                            psnr_count[i]++;
+                        }
+
+                        break;
+                    default:
+                        break;
+                }
+                printf(pkt[i]->kind == VPX_CODEC_CX_FRAME_PKT
+                       && (pkt[i]->data.frame.flags & VPX_FRAME_IS_KEY)? "K":"");
+                fflush(stdout);
+            }
+        }
+        frame_cnt++;
+    }
+    printf("\n");
+    printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
+            frame_cnt,
+            1000 * (float)cx_time / (double)(frame_cnt * 1000000),
+            1000000 * (double)frame_cnt / (double)cx_time);
+
+    fclose(infile);
+
+    printf("Processed %ld frames.\n",(long int)frame_cnt-1);
+    for (i=0; i< NUM_ENCODERS; i++)
+    {
+        /* Calculate PSNR and print it out */
+        if ( (show_psnr) && (psnr_count[i]>0) )
+        {
+            int j;
+            double ovpsnr = sse_to_psnr(psnr_samples_total[i], 255.0,
+                                        psnr_sse_total[i]);
+
+            fprintf(stderr, "\n ENC%d PSNR (Overall/Avg/Y/U/V)", i);
+
+            fprintf(stderr, " %.3lf", ovpsnr);
+            for (j = 0; j < 4; j++)
+            {
+                fprintf(stderr, " %.3lf", psnr_totals[i][j]/psnr_count[i]);
+            }
+        }
+
+        if(vpx_codec_destroy(&codec[i]))
+            die_codec(&codec[i], "Failed to destroy codec");
+
+        vpx_img_free(&raw[i]);
+
+        if(!outfile[i])
+            continue;
+
+        /* Try to rewrite the file header with the actual frame count */
+        if(!fseek(outfile[i], 0, SEEK_SET))
+            write_ivf_file_header(outfile[i], &cfg[i], frame_cnt-1);
+        fclose(outfile[i]);
+    }
+    printf("\n");
+
+    return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/vp8cx_set_ref.c b/src/third_party/libvpx/examples/vp8cx_set_ref.c
new file mode 100644
index 0000000..8b4cc30
--- /dev/null
+++ b/src/third_party/libvpx/examples/vp8cx_set_ref.c
@@ -0,0 +1,194 @@
+/*
+ *  Copyright (c) 2010 The WebM 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.
+ */
+
+
+// VP8 Set Reference Frame
+// =======================
+//
+// This is an example demonstrating how to overwrite the VP8 encoder's
+// internal reference frame. In the sample we set the last frame to the
+// current frame. If this is done at a cut scene it will avoid a keyframe.
+// This technique could be used to bounce between two cameras.
+//
+// Note that the decoder would also have to set the reference frame to the
+// same value on the same frame, or the video will become corrupt.
+//
+// Usage
+// -----
+// This example adds a single argument to the `simple_encoder` example,
+// which specifies the frame number to update the reference frame on.
+// The parameter is parsed as follows:
+//
+//
+// Extra Variables
+// ---------------
+// This example maintains the frame number passed on the command line
+// in the `update_frame_num` variable.
+//
+//
+// Configuration
+// -------------
+//
+// The reference frame is updated on the frame specified on the command
+// line.
+//
+// Observing The Effects
+// ---------------------
+// Use the `simple_encoder` example to encode a sample with a cut scene.
+// Determine the frame number of the cut scene by looking for a generated
+// key-frame (indicated by a 'K'). Supply that frame number as an argument
+// to this example, and observe that no key-frame is generated.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile> <frame>\n",
+          exec_name);
+  exit(EXIT_FAILURE);
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec,
+                        vpx_image_t *img,
+                        int frame_index,
+                        VpxVideoWriter *writer) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1, 0,
+                                               VPX_DL_GOOD_QUALITY);
+  if (res != VPX_CODEC_OK)
+    die_codec(codec, "Failed to encode frame");
+
+  while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
+    got_pkts = 1;
+
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+      if (!vpx_video_writer_write_frame(writer,
+                                        pkt->data.frame.buf,
+                                        pkt->data.frame.sz,
+                                        pkt->data.frame.pts)) {
+        die_codec(codec, "Failed to write compressed frame");
+      }
+
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
+
+  return got_pkts;
+}
+
+int main(int argc, char **argv) {
+  FILE *infile = NULL;
+  vpx_codec_ctx_t codec = {0};
+  vpx_codec_enc_cfg_t cfg = {0};
+  int frame_count = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  VpxVideoInfo info = {0};
+  VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
+  int update_frame_num = 0;
+  const int fps = 30;        // TODO(dkovalev) add command line argument
+  const int bitrate = 200;   // kbit/s TODO(dkovalev) add command line argument
+
+  exec_name = argv[0];
+
+  if (argc != 6)
+    die("Invalid number of arguments");
+
+  // TODO(dkovalev): add vp9 support and rename the file accordingly
+  encoder = get_vpx_encoder_by_name("vp8");
+  if (!encoder)
+    die("Unsupported codec.");
+
+  update_frame_num = atoi(argv[5]);
+  if (!update_frame_num)
+    die("Couldn't parse frame number '%s'\n", argv[5]);
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(argv[1], NULL, 0);
+  info.frame_height = strtol(argv[2], NULL, 0);
+  info.time_base.numerator = 1;
+  info.time_base.denominator = fps;
+
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image.");
+  }
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = info.frame_width;
+  cfg.g_h = info.frame_height;
+  cfg.g_timebase.num = info.time_base.numerator;
+  cfg.g_timebase.den = info.time_base.denominator;
+  cfg.rc_target_bitrate = bitrate;
+
+  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing.", argv[4]);
+
+  if (!(infile = fopen(argv[3], "rb")))
+    die("Failed to open %s for reading.", argv[3]);
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  // Encode frames.
+  while (vpx_img_read(&raw, infile)) {
+    if (frame_count + 1 == update_frame_num) {
+      vpx_ref_frame_t ref;
+      ref.frame_type = VP8_LAST_FRAME;
+      ref.img = raw;
+      if (vpx_codec_control(&codec, VP8_SET_REFERENCE, &ref))
+        die_codec(&codec, "Failed to set reference frame");
+    }
+
+    encode_frame(&codec, &raw, frame_count++, writer);
+  }
+
+  // Flush encoder.
+  while (encode_frame(&codec, NULL, -1, writer)) {}
+
+  printf("\n");
+  fclose(infile);
+  printf("Processed %d frames.\n", frame_count);
+
+  vpx_img_free(&raw);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_writer_close(writer);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/vp9_lossless_encoder.c b/src/third_party/libvpx/examples/vp9_lossless_encoder.c
new file mode 100644
index 0000000..8272516
--- /dev/null
+++ b/src/third_party/libvpx/examples/vp9_lossless_encoder.c
@@ -0,0 +1,144 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 "vpx/vpx_encoder.h"
+#include "vpx/vp8cx.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "vp9_lossless_encoder: Example demonstrating VP9 lossless "
+                  "encoding feature. Supports raw input only.\n");
+  fprintf(stderr, "Usage: %s <width> <height> <infile> <outfile>\n", exec_name);
+  exit(EXIT_FAILURE);
+}
+
+static int encode_frame(vpx_codec_ctx_t *codec,
+                        vpx_image_t *img,
+                        int frame_index,
+                        int flags,
+                        VpxVideoWriter *writer) {
+  int got_pkts = 0;
+  vpx_codec_iter_t iter = NULL;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  const vpx_codec_err_t res = vpx_codec_encode(codec, img, frame_index, 1,
+                                               flags, VPX_DL_GOOD_QUALITY);
+  if (res != VPX_CODEC_OK)
+    die_codec(codec, "Failed to encode frame");
+
+  while ((pkt = vpx_codec_get_cx_data(codec, &iter)) != NULL) {
+    got_pkts = 1;
+
+    if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+      const int keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0;
+      if (!vpx_video_writer_write_frame(writer,
+                                        pkt->data.frame.buf,
+                                        pkt->data.frame.sz,
+                                        pkt->data.frame.pts)) {
+        die_codec(codec, "Failed to write compressed frame");
+      }
+      printf(keyframe ? "K" : ".");
+      fflush(stdout);
+    }
+  }
+
+  return got_pkts;
+}
+
+int main(int argc, char **argv) {
+  FILE *infile = NULL;
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  int frame_count = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  VpxVideoInfo info = {0};
+  VpxVideoWriter *writer = NULL;
+  const VpxInterface *encoder = NULL;
+  const int fps = 30;
+
+  exec_name = argv[0];
+
+  if (argc < 5)
+    die("Invalid number of arguments");
+
+  encoder = get_vpx_encoder_by_name("vp9");
+  if (!encoder)
+     die("Unsupported codec.");
+
+  info.codec_fourcc = encoder->fourcc;
+  info.frame_width = strtol(argv[1], NULL, 0);
+  info.frame_height = strtol(argv[2], NULL, 0);
+  info.time_base.numerator = 1;
+  info.time_base.denominator = fps;
+
+  if (info.frame_width <= 0 ||
+      info.frame_height <= 0 ||
+      (info.frame_width % 2) != 0 ||
+      (info.frame_height % 2) != 0) {
+    die("Invalid frame size: %dx%d", info.frame_width, info.frame_height);
+  }
+
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, info.frame_width,
+                                             info.frame_height, 1)) {
+    die("Failed to allocate image.");
+  }
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res)
+    die_codec(&codec, "Failed to get default codec config.");
+
+  cfg.g_w = info.frame_width;
+  cfg.g_h = info.frame_height;
+  cfg.g_timebase.num = info.time_base.numerator;
+  cfg.g_timebase.den = info.time_base.denominator;
+
+  writer = vpx_video_writer_open(argv[4], kContainerIVF, &info);
+  if (!writer)
+    die("Failed to open %s for writing.", argv[4]);
+
+  if (!(infile = fopen(argv[3], "rb")))
+    die("Failed to open %s for reading.", argv[3]);
+
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+    die_codec(&codec, "Failed to initialize encoder");
+
+  if (vpx_codec_control_(&codec, VP9E_SET_LOSSLESS, 1))
+    die_codec(&codec, "Failed to use lossless mode");
+
+  // Encode frames.
+  while (vpx_img_read(&raw, infile)) {
+    encode_frame(&codec, &raw, frame_count++, 0, writer);
+  }
+
+  // Flush encoder.
+  while (encode_frame(&codec, NULL, -1, 0, writer)) {}
+
+  printf("\n");
+  fclose(infile);
+  printf("Processed %d frames.\n", frame_count);
+
+  vpx_img_free(&raw);
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec.");
+
+  vpx_video_writer_close(writer);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c b/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c
new file mode 100644
index 0000000..271ab70
--- /dev/null
+++ b/src/third_party/libvpx/examples/vp9_spatial_svc_encoder.c
@@ -0,0 +1,919 @@
+/*
+ *  Copyright (c) 2012 The WebM 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.
+ */
+
+/*
+ * This is an example demonstrating how to implement a multi-layer
+ * VP9 encoding scheme based on spatial scalability for video applications
+ * that benefit from a scalable bitstream.
+ */
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+
+#include "../args.h"
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+#include "../vpx_ports/vpx_timer.h"
+#include "vpx/svc_context.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+#include "../vpxstats.h"
+#include "vp9/encoder/vp9_encoder.h"
+#define OUTPUT_RC_STATS 1
+
+static const arg_def_t skip_frames_arg =
+    ARG_DEF("s", "skip-frames", 1, "input frames to skip");
+static const arg_def_t frames_arg =
+    ARG_DEF("f", "frames", 1, "number of frames to encode");
+static const arg_def_t threads_arg =
+    ARG_DEF("th", "threads", 1, "number of threads to use");
+#if OUTPUT_RC_STATS
+static const arg_def_t output_rc_stats_arg =
+    ARG_DEF("rcstat", "output_rc_stats", 1, "output rc stats");
+#endif
+static const arg_def_t width_arg = ARG_DEF("w", "width", 1, "source width");
+static const arg_def_t height_arg = ARG_DEF("h", "height", 1, "source height");
+static const arg_def_t timebase_arg =
+    ARG_DEF("t", "timebase", 1, "timebase (num/den)");
+static const arg_def_t bitrate_arg = ARG_DEF(
+    "b", "target-bitrate", 1, "encoding bitrate, in kilobits per second");
+static const arg_def_t spatial_layers_arg =
+    ARG_DEF("sl", "spatial-layers", 1, "number of spatial SVC layers");
+static const arg_def_t temporal_layers_arg =
+    ARG_DEF("tl", "temporal-layers", 1, "number of temporal SVC layers");
+static const arg_def_t temporal_layering_mode_arg =
+    ARG_DEF("tlm", "temporal-layering-mode", 1, "temporal layering scheme."
+        "VP9E_TEMPORAL_LAYERING_MODE");
+static const arg_def_t kf_dist_arg =
+    ARG_DEF("k", "kf-dist", 1, "number of frames between keyframes");
+static const arg_def_t scale_factors_arg =
+    ARG_DEF("r", "scale-factors", 1, "scale factors (lowest to highest layer)");
+static const arg_def_t passes_arg =
+    ARG_DEF("p", "passes", 1, "Number of passes (1/2)");
+static const arg_def_t pass_arg =
+    ARG_DEF(NULL, "pass", 1, "Pass to execute (1/2)");
+static const arg_def_t fpf_name_arg =
+    ARG_DEF(NULL, "fpf", 1, "First pass statistics file name");
+static const arg_def_t min_q_arg =
+    ARG_DEF(NULL, "min-q", 1, "Minimum quantizer");
+static const arg_def_t max_q_arg =
+    ARG_DEF(NULL, "max-q", 1, "Maximum quantizer");
+static const arg_def_t min_bitrate_arg =
+    ARG_DEF(NULL, "min-bitrate", 1, "Minimum bitrate");
+static const arg_def_t max_bitrate_arg =
+    ARG_DEF(NULL, "max-bitrate", 1, "Maximum bitrate");
+static const arg_def_t lag_in_frame_arg =
+    ARG_DEF(NULL, "lag-in-frames", 1, "Number of frame to input before "
+        "generating any outputs");
+static const arg_def_t rc_end_usage_arg =
+    ARG_DEF(NULL, "rc-end-usage", 1, "0 - 3: VBR, CBR, CQ, Q");
+static const arg_def_t speed_arg =
+    ARG_DEF("sp", "speed", 1, "speed configuration");
+static const arg_def_t aqmode_arg =
+    ARG_DEF("aq", "aqmode", 1, "aq-mode off/on");
+
+#if CONFIG_VP9_HIGHBITDEPTH
+static const struct arg_enum_list bitdepth_enum[] = {
+  {"8",  VPX_BITS_8},
+  {"10", VPX_BITS_10},
+  {"12", VPX_BITS_12},
+  {NULL, 0}
+};
+
+static const arg_def_t bitdepth_arg =
+    ARG_DEF_ENUM("d", "bit-depth", 1, "Bit depth for codec 8, 10 or 12. ",
+                 bitdepth_enum);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+
+static const arg_def_t *svc_args[] = {
+  &frames_arg,        &width_arg,         &height_arg,
+  &timebase_arg,      &bitrate_arg,       &skip_frames_arg, &spatial_layers_arg,
+  &kf_dist_arg,       &scale_factors_arg, &passes_arg,      &pass_arg,
+  &fpf_name_arg,      &min_q_arg,         &max_q_arg,       &min_bitrate_arg,
+  &max_bitrate_arg,   &temporal_layers_arg, &temporal_layering_mode_arg,
+  &lag_in_frame_arg,  &threads_arg,       &aqmode_arg,
+#if OUTPUT_RC_STATS
+  &output_rc_stats_arg,
+#endif
+
+#if CONFIG_VP9_HIGHBITDEPTH
+  &bitdepth_arg,
+#endif
+  &speed_arg,
+  &rc_end_usage_arg,  NULL
+};
+
+static const uint32_t default_frames_to_skip = 0;
+static const uint32_t default_frames_to_code = 60 * 60;
+static const uint32_t default_width = 1920;
+static const uint32_t default_height = 1080;
+static const uint32_t default_timebase_num = 1;
+static const uint32_t default_timebase_den = 60;
+static const uint32_t default_bitrate = 1000;
+static const uint32_t default_spatial_layers = 5;
+static const uint32_t default_temporal_layers = 1;
+static const uint32_t default_kf_dist = 100;
+static const uint32_t default_temporal_layering_mode = 0;
+static const uint32_t default_output_rc_stats = 0;
+static const int32_t default_speed = -1;  // -1 means use library default.
+static const uint32_t default_threads = 0;  // zero means use library default.
+
+typedef struct {
+  const char *input_filename;
+  const char *output_filename;
+  uint32_t frames_to_code;
+  uint32_t frames_to_skip;
+  struct VpxInputContext input_ctx;
+  stats_io_t rc_stats;
+  int passes;
+  int pass;
+} AppInput;
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  fprintf(stderr, "Usage: %s <options> input_filename output_filename\n",
+          exec_name);
+  fprintf(stderr, "Options:\n");
+  arg_show_usage(stderr, svc_args);
+  exit(EXIT_FAILURE);
+}
+
+static void parse_command_line(int argc, const char **argv_,
+                               AppInput *app_input, SvcContext *svc_ctx,
+                               vpx_codec_enc_cfg_t *enc_cfg) {
+  struct arg arg = {0};
+  char **argv = NULL;
+  char **argi = NULL;
+  char **argj = NULL;
+  vpx_codec_err_t res;
+  int passes = 0;
+  int pass = 0;
+  const char *fpf_file_name = NULL;
+  unsigned int min_bitrate = 0;
+  unsigned int max_bitrate = 0;
+  char string_options[1024] = {0};
+
+  // initialize SvcContext with parameters that will be passed to vpx_svc_init
+  svc_ctx->log_level = SVC_LOG_DEBUG;
+  svc_ctx->spatial_layers = default_spatial_layers;
+  svc_ctx->temporal_layers = default_temporal_layers;
+  svc_ctx->temporal_layering_mode = default_temporal_layering_mode;
+#if OUTPUT_RC_STATS
+  svc_ctx->output_rc_stat = default_output_rc_stats;
+#endif
+  svc_ctx->speed = default_speed;
+  svc_ctx->threads = default_threads;
+
+  // start with default encoder configuration
+  res = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), enc_cfg, 0);
+  if (res) {
+    die("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+  }
+  // update enc_cfg with app default values
+  enc_cfg->g_w = default_width;
+  enc_cfg->g_h = default_height;
+  enc_cfg->g_timebase.num = default_timebase_num;
+  enc_cfg->g_timebase.den = default_timebase_den;
+  enc_cfg->rc_target_bitrate = default_bitrate;
+  enc_cfg->kf_min_dist = default_kf_dist;
+  enc_cfg->kf_max_dist = default_kf_dist;
+  enc_cfg->rc_end_usage = VPX_CQ;
+
+  // initialize AppInput with default values
+  app_input->frames_to_code = default_frames_to_code;
+  app_input->frames_to_skip = default_frames_to_skip;
+
+  // process command line options
+  argv = argv_dup(argc - 1, argv_ + 1);
+  for (argi = argj = argv; (*argj = *argi); argi += arg.argv_step) {
+    arg.argv_step = 1;
+
+    if (arg_match(&arg, &frames_arg, argi)) {
+      app_input->frames_to_code = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &width_arg, argi)) {
+      enc_cfg->g_w = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &height_arg, argi)) {
+      enc_cfg->g_h = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &timebase_arg, argi)) {
+      enc_cfg->g_timebase = arg_parse_rational(&arg);
+    } else if (arg_match(&arg, &bitrate_arg, argi)) {
+      enc_cfg->rc_target_bitrate = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &skip_frames_arg, argi)) {
+      app_input->frames_to_skip = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &spatial_layers_arg, argi)) {
+      svc_ctx->spatial_layers = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &temporal_layers_arg, argi)) {
+      svc_ctx->temporal_layers = arg_parse_uint(&arg);
+#if OUTPUT_RC_STATS
+    } else if (arg_match(&arg, &output_rc_stats_arg, argi)) {
+      svc_ctx->output_rc_stat = arg_parse_uint(&arg);
+#endif
+    } else if (arg_match(&arg, &speed_arg, argi)) {
+      svc_ctx->speed = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &aqmode_arg, argi)) {
+      svc_ctx->aqmode = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &threads_arg, argi)) {
+      svc_ctx->threads = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &temporal_layering_mode_arg, argi)) {
+      svc_ctx->temporal_layering_mode =
+          enc_cfg->temporal_layering_mode = arg_parse_int(&arg);
+      if (svc_ctx->temporal_layering_mode) {
+        enc_cfg->g_error_resilient = 1;
+      }
+    } else if (arg_match(&arg, &kf_dist_arg, argi)) {
+      enc_cfg->kf_min_dist = arg_parse_uint(&arg);
+      enc_cfg->kf_max_dist = enc_cfg->kf_min_dist;
+    } else if (arg_match(&arg, &scale_factors_arg, argi)) {
+      snprintf(string_options, sizeof(string_options), "%s scale-factors=%s",
+               string_options, arg.val);
+    } else if (arg_match(&arg, &passes_arg, argi)) {
+      passes = arg_parse_uint(&arg);
+      if (passes < 1 || passes > 2) {
+        die("Error: Invalid number of passes (%d)\n", passes);
+      }
+    } else if (arg_match(&arg, &pass_arg, argi)) {
+      pass = arg_parse_uint(&arg);
+      if (pass < 1 || pass > 2) {
+        die("Error: Invalid pass selected (%d)\n", pass);
+      }
+    } else if (arg_match(&arg, &fpf_name_arg, argi)) {
+      fpf_file_name = arg.val;
+    } else if (arg_match(&arg, &min_q_arg, argi)) {
+      snprintf(string_options, sizeof(string_options), "%s min-quantizers=%s",
+               string_options, arg.val);
+    } else if (arg_match(&arg, &max_q_arg, argi)) {
+      snprintf(string_options, sizeof(string_options), "%s max-quantizers=%s",
+               string_options, arg.val);
+    } else if (arg_match(&arg, &min_bitrate_arg, argi)) {
+      min_bitrate = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &max_bitrate_arg, argi)) {
+      max_bitrate = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &lag_in_frame_arg, argi)) {
+      enc_cfg->g_lag_in_frames = arg_parse_uint(&arg);
+    } else if (arg_match(&arg, &rc_end_usage_arg, argi)) {
+      enc_cfg->rc_end_usage = arg_parse_uint(&arg);
+#if CONFIG_VP9_HIGHBITDEPTH
+    } else if (arg_match(&arg, &bitdepth_arg, argi)) {
+      enc_cfg->g_bit_depth = arg_parse_enum_or_int(&arg);
+      switch (enc_cfg->g_bit_depth) {
+        case VPX_BITS_8:
+          enc_cfg->g_input_bit_depth = 8;
+          enc_cfg->g_profile = 0;
+          break;
+        case VPX_BITS_10:
+          enc_cfg->g_input_bit_depth = 10;
+          enc_cfg->g_profile = 2;
+          break;
+         case VPX_BITS_12:
+          enc_cfg->g_input_bit_depth = 12;
+          enc_cfg->g_profile = 2;
+          break;
+        default:
+          die("Error: Invalid bit depth selected (%d)\n", enc_cfg->g_bit_depth);
+          break;
+      }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    } else {
+      ++argj;
+    }
+  }
+
+  // There will be a space in front of the string options
+  if (strlen(string_options) > 0)
+    vpx_svc_set_options(svc_ctx, string_options + 1);
+
+  if (passes == 0 || passes == 1) {
+    if (pass) {
+      fprintf(stderr, "pass is ignored since there's only one pass\n");
+    }
+    enc_cfg->g_pass = VPX_RC_ONE_PASS;
+  } else {
+    if (pass == 0) {
+      die("pass must be specified when passes is 2\n");
+    }
+
+    if (fpf_file_name == NULL) {
+      die("fpf must be specified when passes is 2\n");
+    }
+
+    if (pass == 1) {
+      enc_cfg->g_pass = VPX_RC_FIRST_PASS;
+      if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 0)) {
+        fatal("Failed to open statistics store");
+      }
+    } else {
+      enc_cfg->g_pass = VPX_RC_LAST_PASS;
+      if (!stats_open_file(&app_input->rc_stats, fpf_file_name, 1)) {
+        fatal("Failed to open statistics store");
+      }
+      enc_cfg->rc_twopass_stats_in = stats_get(&app_input->rc_stats);
+    }
+    app_input->passes = passes;
+    app_input->pass = pass;
+  }
+
+  if (enc_cfg->rc_target_bitrate > 0) {
+    if (min_bitrate > 0) {
+      enc_cfg->rc_2pass_vbr_minsection_pct =
+          min_bitrate * 100 / enc_cfg->rc_target_bitrate;
+    }
+    if (max_bitrate > 0) {
+      enc_cfg->rc_2pass_vbr_maxsection_pct =
+          max_bitrate * 100 / enc_cfg->rc_target_bitrate;
+    }
+  }
+
+  // Check for unrecognized options
+  for (argi = argv; *argi; ++argi)
+    if (argi[0][0] == '-' && strlen(argi[0]) > 1)
+      die("Error: Unrecognized option %s\n", *argi);
+
+  if (argv[0] == NULL || argv[1] == 0) {
+    usage_exit();
+  }
+  app_input->input_filename = argv[0];
+  app_input->output_filename = argv[1];
+  free(argv);
+
+  if (enc_cfg->g_w < 16 || enc_cfg->g_w % 2 || enc_cfg->g_h < 16 ||
+      enc_cfg->g_h % 2)
+    die("Invalid resolution: %d x %d\n", enc_cfg->g_w, enc_cfg->g_h);
+
+  printf(
+      "Codec %s\nframes: %d, skip: %d\n"
+      "layers: %d\n"
+      "width %d, height: %d,\n"
+      "num: %d, den: %d, bitrate: %d,\n"
+      "gop size: %d\n",
+      vpx_codec_iface_name(vpx_codec_vp9_cx()), app_input->frames_to_code,
+      app_input->frames_to_skip,
+      svc_ctx->spatial_layers, enc_cfg->g_w, enc_cfg->g_h,
+      enc_cfg->g_timebase.num, enc_cfg->g_timebase.den,
+      enc_cfg->rc_target_bitrate, enc_cfg->kf_max_dist);
+}
+
+#if OUTPUT_RC_STATS
+// For rate control encoding stats.
+struct RateControlStats {
+  // Number of input frames per layer.
+  int layer_input_frames[VPX_MAX_LAYERS];
+  // Total (cumulative) number of encoded frames per layer.
+  int layer_tot_enc_frames[VPX_MAX_LAYERS];
+  // Number of encoded non-key frames per layer.
+  int layer_enc_frames[VPX_MAX_LAYERS];
+  // Framerate per layer (cumulative).
+  double layer_framerate[VPX_MAX_LAYERS];
+  // Target average frame size per layer (per-frame-bandwidth per layer).
+  double layer_pfb[VPX_MAX_LAYERS];
+  // Actual average frame size per layer.
+  double layer_avg_frame_size[VPX_MAX_LAYERS];
+  // Average rate mismatch per layer (|target - actual| / target).
+  double layer_avg_rate_mismatch[VPX_MAX_LAYERS];
+  // Actual encoding bitrate per layer (cumulative).
+  double layer_encoding_bitrate[VPX_MAX_LAYERS];
+  // Average of the short-time encoder actual bitrate.
+  // TODO(marpan): Should we add these short-time stats for each layer?
+  double avg_st_encoding_bitrate;
+  // Variance of the short-time encoder actual bitrate.
+  double variance_st_encoding_bitrate;
+  // Window (number of frames) for computing short-time encoding bitrate.
+  int window_size;
+  // Number of window measurements.
+  int window_count;
+};
+
+// Note: these rate control stats assume only 1 key frame in the
+// sequence (i.e., first frame only).
+static void set_rate_control_stats(struct RateControlStats *rc,
+                                     vpx_codec_enc_cfg_t *cfg) {
+  unsigned int sl, tl;
+  // Set the layer (cumulative) framerate and the target layer (non-cumulative)
+  // per-frame-bandwidth, for the rate control encoding stats below.
+  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
+
+  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
+    for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
+      const int layer = sl * cfg->ts_number_layers + tl;
+      const int tlayer0 = sl * cfg->ts_number_layers;
+      if (cfg->ts_number_layers == 1)
+        rc->layer_framerate[layer] = framerate;
+      else
+        rc->layer_framerate[layer] =
+          framerate / cfg->ts_rate_decimator[tl];
+      if (tl > 0) {
+        rc->layer_pfb[layer] = 1000.0 *
+            (cfg->layer_target_bitrate[layer] -
+                cfg->layer_target_bitrate[layer - 1]) /
+            (rc->layer_framerate[layer] -
+                rc->layer_framerate[layer - 1]);
+      } else {
+        rc->layer_pfb[tlayer0] = 1000.0 *
+            cfg->layer_target_bitrate[tlayer0] /
+            rc->layer_framerate[tlayer0];
+      }
+      rc->layer_input_frames[layer] = 0;
+      rc->layer_enc_frames[layer] = 0;
+      rc->layer_tot_enc_frames[layer] = 0;
+      rc->layer_encoding_bitrate[layer] = 0.0;
+      rc->layer_avg_frame_size[layer] = 0.0;
+      rc->layer_avg_rate_mismatch[layer] = 0.0;
+    }
+  }
+  rc->window_count = 0;
+  rc->window_size = 15;
+  rc->avg_st_encoding_bitrate = 0.0;
+  rc->variance_st_encoding_bitrate = 0.0;
+}
+
+static void printout_rate_control_summary(struct RateControlStats *rc,
+                                          vpx_codec_enc_cfg_t *cfg,
+                                          int frame_cnt) {
+  unsigned int sl, tl;
+  int tot_num_frames = 0;
+  double perc_fluctuation = 0.0;
+  printf("Total number of processed frames: %d\n\n", frame_cnt - 1);
+  printf("Rate control layer stats for sl%d tl%d layer(s):\n\n",
+      cfg->ss_number_layers, cfg->ts_number_layers);
+  for (sl = 0; sl < cfg->ss_number_layers; ++sl) {
+    for (tl = 0; tl < cfg->ts_number_layers; ++tl) {
+      const int layer = sl * cfg->ts_number_layers + tl;
+      const int num_dropped = (tl > 0) ?
+          (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer]) :
+          (rc->layer_input_frames[layer] - rc->layer_enc_frames[layer] - 1);
+      if (!sl)
+        tot_num_frames += rc->layer_input_frames[layer];
+      rc->layer_encoding_bitrate[layer] = 0.001 * rc->layer_framerate[layer] *
+          rc->layer_encoding_bitrate[layer] / tot_num_frames;
+      rc->layer_avg_frame_size[layer] = rc->layer_avg_frame_size[layer] /
+          rc->layer_enc_frames[layer];
+      rc->layer_avg_rate_mismatch[layer] =
+          100.0 * rc->layer_avg_rate_mismatch[layer] /
+          rc->layer_enc_frames[layer];
+      printf("For layer#: sl%d tl%d \n", sl, tl);
+      printf("Bitrate (target vs actual): %d %f.0 kbps\n",
+             cfg->layer_target_bitrate[layer],
+             rc->layer_encoding_bitrate[layer]);
+      printf("Average frame size (target vs actual): %f %f bits\n",
+             rc->layer_pfb[layer], rc->layer_avg_frame_size[layer]);
+      printf("Average rate_mismatch: %f\n",
+             rc->layer_avg_rate_mismatch[layer]);
+      printf("Number of input frames, encoded (non-key) frames, "
+          "and percent dropped frames: %d %d %f.0 \n",
+          rc->layer_input_frames[layer], rc->layer_enc_frames[layer],
+          100.0 * num_dropped / rc->layer_input_frames[layer]);
+      printf("\n");
+    }
+  }
+  rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
+  rc->variance_st_encoding_bitrate =
+      rc->variance_st_encoding_bitrate / rc->window_count -
+      (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
+  perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
+      rc->avg_st_encoding_bitrate;
+  printf("Short-time stats, for window of %d frames: \n", rc->window_size);
+  printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
+         rc->avg_st_encoding_bitrate,
+         sqrt(rc->variance_st_encoding_bitrate),
+         perc_fluctuation);
+  if (frame_cnt != tot_num_frames)
+    die("Error: Number of input frames not equal to output encoded frames != "
+        "%d tot_num_frames = %d\n", frame_cnt, tot_num_frames);
+}
+
+vpx_codec_err_t parse_superframe_index(const uint8_t *data,
+                                       size_t data_sz,
+                                       uint32_t sizes[8], int *count) {
+  // A chunk ending with a byte matching 0xc0 is an invalid chunk unless
+  // it is a super frame index. If the last byte of real video compression
+  // data is 0xc0 the encoder must add a 0 byte. If we have the marker but
+  // not the associated matching marker byte at the front of the index we have
+  // an invalid bitstream and need to return an error.
+
+  uint8_t marker;
+
+  marker = *(data + data_sz - 1);
+  *count = 0;
+
+
+  if ((marker & 0xe0) == 0xc0) {
+    const uint32_t frames = (marker & 0x7) + 1;
+    const uint32_t mag = ((marker >> 3) & 0x3) + 1;
+    const size_t index_sz = 2 + mag * frames;
+
+    // This chunk is marked as having a superframe index but doesn't have
+    // enough data for it, thus it's an invalid superframe index.
+    if (data_sz < index_sz)
+      return VPX_CODEC_CORRUPT_FRAME;
+
+    {
+      const uint8_t marker2 = *(data + data_sz - index_sz);
+
+      // This chunk is marked as having a superframe index but doesn't have
+      // the matching marker byte at the front of the index therefore it's an
+      // invalid chunk.
+      if (marker != marker2)
+        return VPX_CODEC_CORRUPT_FRAME;
+    }
+
+    {
+      // Found a valid superframe index.
+      uint32_t i, j;
+      const uint8_t *x = &data[data_sz - index_sz + 1];
+
+      for (i = 0; i < frames; ++i) {
+        uint32_t this_sz = 0;
+
+        for (j = 0; j < mag; ++j)
+          this_sz |= (*x++) << (j * 8);
+        sizes[i] = this_sz;
+      }
+      *count = frames;
+    }
+  }
+  return VPX_CODEC_OK;
+}
+#endif
+
+// Example pattern for spatial layers and 2 temporal layers used in the
+// bypass/flexible mode. The pattern corresponds to the pattern
+// VP9E_TEMPORAL_LAYERING_MODE_0101 (temporal_layering_mode == 2) used in
+// non-flexible mode.
+void set_frame_flags_bypass_mode(int sl, int tl, int num_spatial_layers,
+                                 int is_key_frame,
+                                 vpx_svc_ref_frame_config_t *ref_frame_config) {
+  for (sl = 0; sl < num_spatial_layers; ++sl) {
+    if (!tl) {
+      if (!sl) {
+        ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
+                                            VP8_EFLAG_NO_REF_ARF |
+                                            VP8_EFLAG_NO_UPD_GF |
+                                            VP8_EFLAG_NO_UPD_ARF;
+      } else {
+        if (is_key_frame) {
+          ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_LAST |
+                                              VP8_EFLAG_NO_REF_ARF |
+                                              VP8_EFLAG_NO_UPD_GF |
+                                              VP8_EFLAG_NO_UPD_ARF;
+        } else {
+        ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
+                                            VP8_EFLAG_NO_UPD_GF |
+                                            VP8_EFLAG_NO_UPD_ARF;
+        }
+      }
+    } else if (tl == 1) {
+      if (!sl) {
+        ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_GF |
+                                            VP8_EFLAG_NO_REF_ARF |
+                                            VP8_EFLAG_NO_UPD_LAST |
+                                            VP8_EFLAG_NO_UPD_GF;
+      } else {
+        ref_frame_config->frame_flags[sl] = VP8_EFLAG_NO_REF_ARF |
+                                            VP8_EFLAG_NO_UPD_LAST |
+                                            VP8_EFLAG_NO_UPD_GF;
+      }
+    }
+    if (tl == 0) {
+      ref_frame_config->lst_fb_idx[sl] = sl;
+      if (sl)
+        ref_frame_config->gld_fb_idx[sl] = sl - 1;
+      else
+        ref_frame_config->gld_fb_idx[sl] = 0;
+      ref_frame_config->alt_fb_idx[sl] = 0;
+    } else if (tl == 1) {
+      ref_frame_config->lst_fb_idx[sl] = sl;
+      ref_frame_config->gld_fb_idx[sl] = num_spatial_layers + sl - 1;
+      ref_frame_config->alt_fb_idx[sl] = num_spatial_layers + sl;
+    }
+  }
+}
+
+int main(int argc, const char **argv) {
+  AppInput app_input = {0};
+  VpxVideoWriter *writer = NULL;
+  VpxVideoInfo info = {0};
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t enc_cfg;
+  SvcContext svc_ctx;
+  uint32_t i;
+  uint32_t frame_cnt = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  int pts = 0;            /* PTS starts at 0 */
+  int frame_duration = 1; /* 1 timebase tick per frame */
+  FILE *infile = NULL;
+  int end_of_stream = 0;
+  int frames_received = 0;
+#if OUTPUT_RC_STATS
+  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
+  struct RateControlStats rc;
+  vpx_svc_layer_id_t layer_id;
+  vpx_svc_ref_frame_config_t ref_frame_config;
+  int sl, tl;
+  double sum_bitrate = 0.0;
+  double sum_bitrate2 = 0.0;
+  double framerate  = 30.0;
+#endif
+  struct vpx_usec_timer timer;
+  int64_t cx_time = 0;
+  memset(&svc_ctx, 0, sizeof(svc_ctx));
+  svc_ctx.log_print = 1;
+  exec_name = argv[0];
+  parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
+
+  // Allocate image buffer
+#if CONFIG_VP9_HIGHBITDEPTH
+  if (!vpx_img_alloc(&raw, enc_cfg.g_input_bit_depth == 8 ?
+                         VPX_IMG_FMT_I420 : VPX_IMG_FMT_I42016,
+                     enc_cfg.g_w, enc_cfg.g_h, 32)) {
+    die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
+  }
+#else
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, enc_cfg.g_w, enc_cfg.g_h, 32)) {
+    die("Failed to allocate image %dx%d\n", enc_cfg.g_w, enc_cfg.g_h);
+  }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+  if (!(infile = fopen(app_input.input_filename, "rb")))
+    die("Failed to open %s for reading\n", app_input.input_filename);
+
+  // Initialize codec
+  if (vpx_svc_init(&svc_ctx, &codec, vpx_codec_vp9_cx(), &enc_cfg) !=
+      VPX_CODEC_OK)
+    die("Failed to initialize encoder\n");
+
+#if OUTPUT_RC_STATS
+  if (svc_ctx.output_rc_stat) {
+    set_rate_control_stats(&rc, &enc_cfg);
+    framerate = enc_cfg.g_timebase.den / enc_cfg.g_timebase.num;
+  }
+#endif
+
+  info.codec_fourcc = VP9_FOURCC;
+  info.time_base.numerator = enc_cfg.g_timebase.num;
+  info.time_base.denominator = enc_cfg.g_timebase.den;
+
+  if (!(app_input.passes == 2 && app_input.pass == 1)) {
+    // We don't save the bitstream for the 1st pass on two pass rate control
+    writer = vpx_video_writer_open(app_input.output_filename, kContainerIVF,
+                                   &info);
+    if (!writer)
+      die("Failed to open %s for writing\n", app_input.output_filename);
+  }
+#if OUTPUT_RC_STATS
+  // For now, just write temporal layer streams.
+  // TODO(wonkap): do spatial by re-writing superframe.
+  if (svc_ctx.output_rc_stat) {
+    for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
+      char file_name[PATH_MAX];
+
+      snprintf(file_name, sizeof(file_name), "%s_t%d.ivf",
+               app_input.output_filename, tl);
+      outfile[tl] = vpx_video_writer_open(file_name, kContainerIVF, &info);
+      if (!outfile[tl])
+        die("Failed to open %s for writing", file_name);
+    }
+  }
+#endif
+
+  // skip initial frames
+  for (i = 0; i < app_input.frames_to_skip; ++i)
+    vpx_img_read(&raw, infile);
+
+  if (svc_ctx.speed != -1)
+    vpx_codec_control(&codec, VP8E_SET_CPUUSED, svc_ctx.speed);
+  if (svc_ctx.threads)
+    vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (svc_ctx.threads >> 1));
+  if (svc_ctx.speed >= 5 && svc_ctx.aqmode == 1)
+    vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
+
+
+  // Encode frames
+  while (!end_of_stream) {
+    vpx_codec_iter_t iter = NULL;
+    const vpx_codec_cx_pkt_t *cx_pkt;
+    if (frame_cnt >= app_input.frames_to_code || !vpx_img_read(&raw, infile)) {
+      // We need one extra vpx_svc_encode call at end of stream to flush
+      // encoder and get remaining data
+      end_of_stream = 1;
+    }
+
+    // For BYPASS/FLEXIBLE mode, set the frame flags (reference and updates)
+    // and the buffer indices for each spatial layer of the current
+    // (super)frame to be encoded. The temporal layer_id for the current frame
+    // also needs to be set.
+    // TODO(marpan): Should rename the "VP9E_TEMPORAL_LAYERING_MODE_BYPASS"
+    // mode to "VP9E_LAYERING_MODE_BYPASS".
+    if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
+      layer_id.spatial_layer_id = 0;
+      // Example for 2 temporal layers.
+      if (frame_cnt % 2 == 0)
+        layer_id.temporal_layer_id = 0;
+      else
+        layer_id.temporal_layer_id = 1;
+      // Note that we only set the temporal layer_id, since we are calling
+      // the encode for the whole superframe. The encoder will internally loop
+      // over all the spatial layers for the current superframe.
+      vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
+      set_frame_flags_bypass_mode(sl, layer_id.temporal_layer_id,
+                                  svc_ctx.spatial_layers,
+                                  frame_cnt == 0,
+                                  &ref_frame_config);
+      vpx_codec_control(&codec, VP9E_SET_SVC_REF_FRAME_CONFIG,
+                        &ref_frame_config);
+      // Keep track of input frames, to account for frame drops in rate control
+      // stats/metrics.
+      for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+        ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
+                                layer_id.temporal_layer_id];
+      }
+    }
+
+    vpx_usec_timer_start(&timer);
+    res = vpx_svc_encode(&svc_ctx, &codec, (end_of_stream ? NULL : &raw),
+                         pts, frame_duration, svc_ctx.speed >= 5 ?
+                         VPX_DL_REALTIME : VPX_DL_GOOD_QUALITY);
+    vpx_usec_timer_mark(&timer);
+    cx_time += vpx_usec_timer_elapsed(&timer);
+
+    printf("%s", vpx_svc_get_message(&svc_ctx));
+    fflush(stdout);
+    if (res != VPX_CODEC_OK) {
+      die_codec(&codec, "Failed to encode frame");
+    }
+
+    while ((cx_pkt = vpx_codec_get_cx_data(&codec, &iter)) != NULL) {
+      switch (cx_pkt->kind) {
+        case VPX_CODEC_CX_FRAME_PKT: {
+          SvcInternal_t *const si = (SvcInternal_t *)svc_ctx.internal;
+          if (cx_pkt->data.frame.sz > 0) {
+#if OUTPUT_RC_STATS
+            uint32_t sizes[8];
+            int count = 0;
+#endif
+            vpx_video_writer_write_frame(writer,
+                                         cx_pkt->data.frame.buf,
+                                         cx_pkt->data.frame.sz,
+                                         cx_pkt->data.frame.pts);
+#if OUTPUT_RC_STATS
+            // TODO(marpan/wonkap): Put this (to line728) in separate function.
+            if (svc_ctx.output_rc_stat) {
+              vpx_codec_control(&codec, VP9E_GET_SVC_LAYER_ID, &layer_id);
+              parse_superframe_index(cx_pkt->data.frame.buf,
+                                     cx_pkt->data.frame.sz, sizes, &count);
+              // Note computing input_layer_frames here won't account for frame
+              // drops in rate control stats.
+              // TODO(marpan): Fix this for non-bypass mode so we can get stats
+              // for dropped frames.
+              if (svc_ctx.temporal_layering_mode !=
+                  VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
+                for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+                  ++rc.layer_input_frames[sl * enc_cfg.ts_number_layers +
+                                         layer_id.temporal_layer_id];
+                }
+              }
+              for (tl = layer_id.temporal_layer_id;
+                  tl < enc_cfg.ts_number_layers; ++tl) {
+                vpx_video_writer_write_frame(outfile[tl],
+                                             cx_pkt->data.frame.buf,
+                                             cx_pkt->data.frame.sz,
+                                             cx_pkt->data.frame.pts);
+              }
+
+              for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+                for (tl = layer_id.temporal_layer_id;
+                    tl < enc_cfg.ts_number_layers; ++tl) {
+                  const int layer = sl * enc_cfg.ts_number_layers + tl;
+                  ++rc.layer_tot_enc_frames[layer];
+                  rc.layer_encoding_bitrate[layer] += 8.0 * sizes[sl];
+                  // Keep count of rate control stats per layer, for non-key
+                  // frames.
+                  if (tl == layer_id.temporal_layer_id &&
+                      !(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
+                    rc.layer_avg_frame_size[layer] += 8.0 * sizes[sl];
+                    rc.layer_avg_rate_mismatch[layer] +=
+                        fabs(8.0 * sizes[sl] - rc.layer_pfb[layer]) /
+                        rc.layer_pfb[layer];
+                    ++rc.layer_enc_frames[layer];
+                  }
+                }
+              }
+
+              // Update for short-time encoding bitrate states, for moving
+              // window of size rc->window, shifted by rc->window / 2.
+              // Ignore first window segment, due to key frame.
+              if (frame_cnt > rc.window_size) {
+                tl = layer_id.temporal_layer_id;
+                for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+                  sum_bitrate += 0.001 * 8.0 * sizes[sl] * framerate;
+                }
+                if (frame_cnt % rc.window_size == 0) {
+                  rc.window_count += 1;
+                  rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
+                  rc.variance_st_encoding_bitrate +=
+                      (sum_bitrate / rc.window_size) *
+                      (sum_bitrate / rc.window_size);
+                  sum_bitrate = 0.0;
+                }
+              }
+
+              // Second shifted window.
+              if (frame_cnt > rc.window_size + rc.window_size / 2) {
+               tl = layer_id.temporal_layer_id;
+               for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+                 sum_bitrate2 += 0.001 * 8.0 * sizes[sl] * framerate;
+               }
+
+               if (frame_cnt > 2 * rc.window_size &&
+                  frame_cnt % rc.window_size == 0) {
+                 rc.window_count += 1;
+                 rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
+                 rc.variance_st_encoding_bitrate +=
+                    (sum_bitrate2 / rc.window_size) *
+                    (sum_bitrate2 / rc.window_size);
+                 sum_bitrate2 = 0.0;
+               }
+              }
+            }
+#endif
+          }
+
+          printf("SVC frame: %d, kf: %d, size: %d, pts: %d\n", frames_received,
+                 !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY),
+                 (int)cx_pkt->data.frame.sz, (int)cx_pkt->data.frame.pts);
+          if (enc_cfg.ss_number_layers == 1 && enc_cfg.ts_number_layers == 1)
+            si->bytes_sum[0] += (int)cx_pkt->data.frame.sz;
+          ++frames_received;
+          break;
+        }
+        case VPX_CODEC_STATS_PKT: {
+          stats_write(&app_input.rc_stats,
+                      cx_pkt->data.twopass_stats.buf,
+                      cx_pkt->data.twopass_stats.sz);
+          break;
+        }
+        default: {
+          break;
+        }
+      }
+    }
+
+    if (!end_of_stream) {
+      ++frame_cnt;
+      pts += frame_duration;
+    }
+  }
+
+  // Compensate for the extra frame count for the bypass mode.
+  if (svc_ctx.temporal_layering_mode == VP9E_TEMPORAL_LAYERING_MODE_BYPASS) {
+    for (sl = 0; sl < enc_cfg.ss_number_layers; ++sl) {
+      const int layer = sl * enc_cfg.ts_number_layers +
+          layer_id.temporal_layer_id;
+      --rc.layer_input_frames[layer];
+    }
+  }
+
+  printf("Processed %d frames\n", frame_cnt);
+  fclose(infile);
+#if OUTPUT_RC_STATS
+  if (svc_ctx.output_rc_stat) {
+    printout_rate_control_summary(&rc, &enc_cfg, frame_cnt);
+    printf("\n");
+  }
+#endif
+  if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
+  if (app_input.passes == 2)
+    stats_close(&app_input.rc_stats, 1);
+  if (writer) {
+    vpx_video_writer_close(writer);
+  }
+#if OUTPUT_RC_STATS
+  if (svc_ctx.output_rc_stat) {
+    for (tl = 0; tl < enc_cfg.ts_number_layers; ++tl) {
+      vpx_video_writer_close(outfile[tl]);
+    }
+  }
+#endif
+  printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
+         frame_cnt,
+         1000 * (float)cx_time / (double)(frame_cnt * 1000000),
+         1000000 * (double)frame_cnt / (double)cx_time);
+  vpx_img_free(&raw);
+  // display average size, psnr
+  printf("%s", vpx_svc_dump_statistics(&svc_ctx));
+  vpx_svc_release(&svc_ctx);
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c b/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c
new file mode 100644
index 0000000..e6c09fb
--- /dev/null
+++ b/src/third_party/libvpx/examples/vpx_temporal_svc_encoder.c
@@ -0,0 +1,852 @@
+/*
+ *  Copyright (c) 2012 The WebM 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.
+ */
+
+//  This is an example demonstrating how to implement a multi-layer VPx
+//  encoding scheme based on temporal scalability for video applications
+//  that benefit from a scalable bitstream.
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "./vpx_config.h"
+#include "../vpx_ports/vpx_timer.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+#include "../tools_common.h"
+#include "../video_writer.h"
+
+static const char *exec_name;
+
+void usage_exit(void) {
+  exit(EXIT_FAILURE);
+}
+
+// Denoiser states, for temporal denoising.
+enum denoiserState {
+  kDenoiserOff,
+  kDenoiserOnYOnly,
+  kDenoiserOnYUV,
+  kDenoiserOnYUVAggressive,
+  kDenoiserOnAdaptive
+};
+
+static int mode_to_num_layers[13] = {1, 2, 2, 3, 3, 3, 3, 5, 2, 3, 3, 3, 3};
+
+// For rate control encoding stats.
+struct RateControlMetrics {
+  // Number of input frames per layer.
+  int layer_input_frames[VPX_TS_MAX_LAYERS];
+  // Total (cumulative) number of encoded frames per layer.
+  int layer_tot_enc_frames[VPX_TS_MAX_LAYERS];
+  // Number of encoded non-key frames per layer.
+  int layer_enc_frames[VPX_TS_MAX_LAYERS];
+  // Framerate per layer layer (cumulative).
+  double layer_framerate[VPX_TS_MAX_LAYERS];
+  // Target average frame size per layer (per-frame-bandwidth per layer).
+  double layer_pfb[VPX_TS_MAX_LAYERS];
+  // Actual average frame size per layer.
+  double layer_avg_frame_size[VPX_TS_MAX_LAYERS];
+  // Average rate mismatch per layer (|target - actual| / target).
+  double layer_avg_rate_mismatch[VPX_TS_MAX_LAYERS];
+  // Actual encoding bitrate per layer (cumulative).
+  double layer_encoding_bitrate[VPX_TS_MAX_LAYERS];
+  // Average of the short-time encoder actual bitrate.
+  // TODO(marpan): Should we add these short-time stats for each layer?
+  double avg_st_encoding_bitrate;
+  // Variance of the short-time encoder actual bitrate.
+  double variance_st_encoding_bitrate;
+  // Window (number of frames) for computing short-timee encoding bitrate.
+  int window_size;
+  // Number of window measurements.
+  int window_count;
+  int layer_target_bitrate[VPX_MAX_LAYERS];
+};
+
+// Note: these rate control metrics assume only 1 key frame in the
+// sequence (i.e., first frame only). So for temporal pattern# 7
+// (which has key frame for every frame on base layer), the metrics
+// computation will be off/wrong.
+// TODO(marpan): Update these metrics to account for multiple key frames
+// in the stream.
+static void set_rate_control_metrics(struct RateControlMetrics *rc,
+                                     vpx_codec_enc_cfg_t *cfg) {
+  unsigned int i = 0;
+  // Set the layer (cumulative) framerate and the target layer (non-cumulative)
+  // per-frame-bandwidth, for the rate control encoding stats below.
+  const double framerate = cfg->g_timebase.den / cfg->g_timebase.num;
+  rc->layer_framerate[0] = framerate / cfg->ts_rate_decimator[0];
+  rc->layer_pfb[0] = 1000.0 * rc->layer_target_bitrate[0] /
+      rc->layer_framerate[0];
+  for (i = 0; i < cfg->ts_number_layers; ++i) {
+    if (i > 0) {
+      rc->layer_framerate[i] = framerate / cfg->ts_rate_decimator[i];
+      rc->layer_pfb[i] = 1000.0 *
+          (rc->layer_target_bitrate[i] - rc->layer_target_bitrate[i - 1]) /
+          (rc->layer_framerate[i] - rc->layer_framerate[i - 1]);
+    }
+    rc->layer_input_frames[i] = 0;
+    rc->layer_enc_frames[i] = 0;
+    rc->layer_tot_enc_frames[i] = 0;
+    rc->layer_encoding_bitrate[i] = 0.0;
+    rc->layer_avg_frame_size[i] = 0.0;
+    rc->layer_avg_rate_mismatch[i] = 0.0;
+  }
+  rc->window_count = 0;
+  rc->window_size = 15;
+  rc->avg_st_encoding_bitrate = 0.0;
+  rc->variance_st_encoding_bitrate = 0.0;
+}
+
+static void printout_rate_control_summary(struct RateControlMetrics *rc,
+                                          vpx_codec_enc_cfg_t *cfg,
+                                          int frame_cnt) {
+  unsigned int i = 0;
+  int tot_num_frames = 0;
+  double perc_fluctuation = 0.0;
+  printf("Total number of processed frames: %d\n\n", frame_cnt -1);
+  printf("Rate control layer stats for %d layer(s):\n\n",
+      cfg->ts_number_layers);
+  for (i = 0; i < cfg->ts_number_layers; ++i) {
+    const int num_dropped = (i > 0) ?
+        (rc->layer_input_frames[i] - rc->layer_enc_frames[i]) :
+        (rc->layer_input_frames[i] - rc->layer_enc_frames[i] - 1);
+    tot_num_frames += rc->layer_input_frames[i];
+    rc->layer_encoding_bitrate[i] = 0.001 * rc->layer_framerate[i] *
+        rc->layer_encoding_bitrate[i] / tot_num_frames;
+    rc->layer_avg_frame_size[i] = rc->layer_avg_frame_size[i] /
+        rc->layer_enc_frames[i];
+    rc->layer_avg_rate_mismatch[i] = 100.0 * rc->layer_avg_rate_mismatch[i] /
+        rc->layer_enc_frames[i];
+    printf("For layer#: %d \n", i);
+    printf("Bitrate (target vs actual): %d %f \n", rc->layer_target_bitrate[i],
+           rc->layer_encoding_bitrate[i]);
+    printf("Average frame size (target vs actual): %f %f \n", rc->layer_pfb[i],
+           rc->layer_avg_frame_size[i]);
+    printf("Average rate_mismatch: %f \n", rc->layer_avg_rate_mismatch[i]);
+    printf("Number of input frames, encoded (non-key) frames, "
+        "and perc dropped frames: %d %d %f \n", rc->layer_input_frames[i],
+        rc->layer_enc_frames[i],
+        100.0 * num_dropped / rc->layer_input_frames[i]);
+    printf("\n");
+  }
+  rc->avg_st_encoding_bitrate = rc->avg_st_encoding_bitrate / rc->window_count;
+  rc->variance_st_encoding_bitrate =
+      rc->variance_st_encoding_bitrate / rc->window_count -
+      (rc->avg_st_encoding_bitrate * rc->avg_st_encoding_bitrate);
+  perc_fluctuation = 100.0 * sqrt(rc->variance_st_encoding_bitrate) /
+      rc->avg_st_encoding_bitrate;
+  printf("Short-time stats, for window of %d frames: \n",rc->window_size);
+  printf("Average, rms-variance, and percent-fluct: %f %f %f \n",
+         rc->avg_st_encoding_bitrate,
+         sqrt(rc->variance_st_encoding_bitrate),
+         perc_fluctuation);
+  if ((frame_cnt - 1) != tot_num_frames)
+    die("Error: Number of input frames not equal to output! \n");
+}
+
+// Temporal scaling parameters:
+// NOTE: The 3 prediction frames cannot be used interchangeably due to
+// differences in the way they are handled throughout the code. The
+// frames should be allocated to layers in the order LAST, GF, ARF.
+// Other combinations work, but may produce slightly inferior results.
+static void set_temporal_layer_pattern(int layering_mode,
+                                       vpx_codec_enc_cfg_t *cfg,
+                                       int *layer_flags,
+                                       int *flag_periodicity) {
+  switch (layering_mode) {
+    case 0: {
+      // 1-layer.
+      int ids[1] = {0};
+      cfg->ts_periodicity = 1;
+      *flag_periodicity = 1;
+      cfg->ts_number_layers = 1;
+      cfg->ts_rate_decimator[0] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // Update L only.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF;
+      break;
+    }
+    case 1: {
+      // 2-layers, 2-frame period.
+      int ids[2] = {0, 1};
+      cfg->ts_periodicity = 2;
+      *flag_periodicity = 2;
+      cfg->ts_number_layers = 2;
+      cfg->ts_rate_decimator[0] = 2;
+      cfg->ts_rate_decimator[1] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+#if 1
+      // 0=L, 1=GF, Intra-layer prediction enabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_REF_ARF;
+#else
+       // 0=L, 1=GF, Intra-layer prediction disabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      layer_flags[1] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_REF_LAST;
+#endif
+      break;
+    }
+    case 2: {
+      // 2-layers, 3-frame period.
+      int ids[3] = {0, 1, 1};
+      cfg->ts_periodicity = 3;
+      *flag_periodicity = 3;
+      cfg->ts_number_layers = 2;
+      cfg->ts_rate_decimator[0] = 3;
+      cfg->ts_rate_decimator[1] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, Intra-layer prediction enabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[1] =
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF  | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      break;
+    }
+    case 3: {
+      // 3-layers, 6-frame period.
+      int ids[6] = {0, 2, 2, 1, 2, 2};
+      cfg->ts_periodicity = 6;
+      *flag_periodicity = 6;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 6;
+      cfg->ts_rate_decimator[1] = 3;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_UPD_LAST;
+      layer_flags[1] =
+      layer_flags[2] =
+      layer_flags[4] =
+      layer_flags[5] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+      break;
+    }
+    case 4: {
+      // 3-layers, 4-frame period.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 4;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      layer_flags[1] =
+      layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      break;
+    }
+    case 5: {
+      // 3-layers, 4-frame period.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 4;
+      cfg->ts_number_layers     = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled in layer 1, disabled
+      // in layer 2.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[1] =
+      layer_flags[3] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      break;
+    }
+    case 6: {
+      // 3-layers, 4-frame period.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 4;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF, Intra-layer prediction enabled.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[2] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[1] =
+      layer_flags[3] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+      break;
+    }
+    case 7: {
+      // NOTE: Probably of academic interest only.
+      // 5-layers, 16-frame period.
+      int ids[16] = {0, 4, 3, 4, 2, 4, 3, 4, 1, 4, 3, 4, 2, 4, 3, 4};
+      cfg->ts_periodicity = 16;
+      *flag_periodicity = 16;
+      cfg->ts_number_layers = 5;
+      cfg->ts_rate_decimator[0] = 16;
+      cfg->ts_rate_decimator[1] = 8;
+      cfg->ts_rate_decimator[2] = 4;
+      cfg->ts_rate_decimator[3] = 2;
+      cfg->ts_rate_decimator[4] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      layer_flags[0]  = VPX_EFLAG_FORCE_KF;
+      layer_flags[1]  =
+      layer_flags[3]  =
+      layer_flags[5]  =
+      layer_flags[7]  =
+      layer_flags[9]  =
+      layer_flags[11] =
+      layer_flags[13] =
+      layer_flags[15] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[2]  =
+      layer_flags[6]  =
+      layer_flags[10] =
+      layer_flags[14] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_GF;
+      layer_flags[4] =
+      layer_flags[12] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[8]  = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_GF;
+      break;
+    }
+    case 8: {
+      // 2-layers, with sync point at first frame of layer 1.
+      int ids[2] = {0, 1};
+      cfg->ts_periodicity = 2;
+      *flag_periodicity = 8;
+      cfg->ts_number_layers = 2;
+      cfg->ts_rate_decimator[0] = 2;
+      cfg->ts_rate_decimator[1] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF.
+      // ARF is used as predictor for all frames, and is only updated on
+      // key frame. Sync point every 8 frames.
+
+      // Layer 0: predict from L and ARF, update L and G.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_UPD_ARF;
+      // Layer 1: sync point: predict from L and ARF, and update G.
+      layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ARF;
+      // Layer 0, predict from L and ARF, update L.
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF  | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF;
+      // Layer 1: predict from L, G and ARF, and update G.
+      layer_flags[3] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ENTROPY;
+      // Layer 0.
+      layer_flags[4] = layer_flags[2];
+      // Layer 1.
+      layer_flags[5] = layer_flags[3];
+      // Layer 0.
+      layer_flags[6] = layer_flags[4];
+      // Layer 1.
+      layer_flags[7] = layer_flags[5];
+     break;
+    }
+    case 9: {
+      // 3-layers: Sync points for layer 1 and 2 every 8 frames.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 8;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF  | VP8_EFLAG_NO_REF_GF |
+          VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF   | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[3] =
+      layer_flags[5] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+      layer_flags[4] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[6] = VP8_EFLAG_NO_REF_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[7] = VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_ENTROPY;
+      break;
+    }
+    case 10: {
+      // 3-layers structure where ARF is used as predictor for all frames,
+      // and is only updated on key frame.
+      // Sync points for layer 1 and 2 every 8 frames.
+
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 8;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF.
+      // Layer 0: predict from L and ARF; update L and G.
+      layer_flags[0] = VPX_EFLAG_FORCE_KF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_REF_GF;
+      // Layer 2: sync point: predict from L and ARF; update none.
+      layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+          VP8_EFLAG_NO_UPD_ENTROPY;
+      // Layer 1: sync point: predict from L and ARF; update G.
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_UPD_LAST;
+      // Layer 2: predict from L, G, ARF; update none.
+      layer_flags[3] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
+      // Layer 0: predict from L and ARF; update L.
+      layer_flags[4] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_REF_GF;
+      // Layer 2: predict from L, G, ARF; update none.
+      layer_flags[5] = layer_flags[3];
+      // Layer 1: predict from L, G, ARF; update G.
+      layer_flags[6] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      // Layer 2: predict from L, G, ARF; update none.
+      layer_flags[7] = layer_flags[3];
+      break;
+    }
+    case 11: {
+      // 3-layers structure with one reference frame.
+      // This works same as temporal_layering_mode 3.
+      // This was added to compare with vp9_spatial_svc_encoder.
+
+      // 3-layers, 4-frame period.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 4;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF, Intra-layer prediction disabled.
+      layer_flags[0] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF;
+      layer_flags[2] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      layer_flags[1] = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+      layer_flags[3] = VP8_EFLAG_NO_REF_LAST | VP8_EFLAG_NO_REF_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_GF;
+      break;
+    }
+    case 12:
+    default: {
+      // 3-layers structure as in case 10, but no sync/refresh points for
+      // layer 1 and 2.
+      int ids[4] = {0, 2, 1, 2};
+      cfg->ts_periodicity = 4;
+      *flag_periodicity = 8;
+      cfg->ts_number_layers = 3;
+      cfg->ts_rate_decimator[0] = 4;
+      cfg->ts_rate_decimator[1] = 2;
+      cfg->ts_rate_decimator[2] = 1;
+      memcpy(cfg->ts_layer_id, ids, sizeof(ids));
+      // 0=L, 1=GF, 2=ARF.
+      // Layer 0: predict from L and ARF; update L.
+      layer_flags[0] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_REF_GF;
+      layer_flags[4] = layer_flags[0];
+      // Layer 1: predict from L, G, ARF; update G.
+      layer_flags[2] = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      layer_flags[6] = layer_flags[2];
+      // Layer 2: predict from L, G, ARF; update none.
+      layer_flags[1] = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+          VP8_EFLAG_NO_UPD_LAST | VP8_EFLAG_NO_UPD_ENTROPY;
+      layer_flags[3] = layer_flags[1];
+      layer_flags[5] = layer_flags[1];
+      layer_flags[7] = layer_flags[1];
+      break;
+    }
+  }
+}
+
+int main(int argc, char **argv) {
+  VpxVideoWriter *outfile[VPX_TS_MAX_LAYERS] = {NULL};
+  vpx_codec_ctx_t codec;
+  vpx_codec_enc_cfg_t cfg;
+  int frame_cnt = 0;
+  vpx_image_t raw;
+  vpx_codec_err_t res;
+  unsigned int width;
+  unsigned int height;
+  int speed;
+  int frame_avail;
+  int got_data;
+  int flags = 0;
+  unsigned int i;
+  int pts = 0;  // PTS starts at 0.
+  int frame_duration = 1;  // 1 timebase tick per frame.
+  int layering_mode = 0;
+  int layer_flags[VPX_TS_MAX_PERIODICITY] = {0};
+  int flag_periodicity = 1;
+#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
+  vpx_svc_layer_id_t layer_id = {0, 0};
+#else
+  vpx_svc_layer_id_t layer_id = {0};
+#endif
+  const VpxInterface *encoder = NULL;
+  FILE *infile = NULL;
+  struct RateControlMetrics rc;
+  int64_t cx_time = 0;
+  const int min_args_base = 11;
+#if CONFIG_VP9_HIGHBITDEPTH
+  vpx_bit_depth_t bit_depth = VPX_BITS_8;
+  int input_bit_depth = 8;
+  const int min_args = min_args_base + 1;
+#else
+  const int min_args = min_args_base;
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  double sum_bitrate = 0.0;
+  double sum_bitrate2 = 0.0;
+  double framerate  = 30.0;
+
+  exec_name = argv[0];
+  // Check usage and arguments.
+  if (argc < min_args) {
+#if CONFIG_VP9_HIGHBITDEPTH
+    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
+        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
+        "<Rate_0> ... <Rate_nlayers-1> <bit-depth> \n", argv[0]);
+#else
+    die("Usage: %s <infile> <outfile> <codec_type(vp8/vp9)> <width> <height> "
+        "<rate_num> <rate_den> <speed> <frame_drop_threshold> <mode> "
+        "<Rate_0> ... <Rate_nlayers-1> \n", argv[0]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  }
+
+  encoder = get_vpx_encoder_by_name(argv[3]);
+  if (!encoder)
+    die("Unsupported codec.");
+
+  printf("Using %s\n", vpx_codec_iface_name(encoder->codec_interface()));
+
+  width = strtol(argv[4], NULL, 0);
+  height = strtol(argv[5], NULL, 0);
+  if (width < 16 || width % 2 || height < 16 || height % 2) {
+    die("Invalid resolution: %d x %d", width, height);
+  }
+
+  layering_mode = strtol(argv[10], NULL, 0);
+  if (layering_mode < 0 || layering_mode > 13) {
+    die("Invalid layering mode (0..12) %s", argv[10]);
+  }
+
+  if (argc != min_args + mode_to_num_layers[layering_mode]) {
+    die("Invalid number of arguments");
+  }
+
+#if CONFIG_VP9_HIGHBITDEPTH
+  switch (strtol(argv[argc-1], NULL, 0)) {
+    case 8:
+      bit_depth = VPX_BITS_8;
+      input_bit_depth = 8;
+      break;
+    case 10:
+      bit_depth = VPX_BITS_10;
+      input_bit_depth = 10;
+      break;
+    case 12:
+      bit_depth = VPX_BITS_12;
+      input_bit_depth = 12;
+      break;
+    default:
+      die("Invalid bit depth (8, 10, 12) %s", argv[argc-1]);
+  }
+  if (!vpx_img_alloc(&raw,
+                     bit_depth == VPX_BITS_8 ? VPX_IMG_FMT_I420 :
+                                               VPX_IMG_FMT_I42016,
+                     width, height, 32)) {
+    die("Failed to allocate image", width, height);
+  }
+#else
+  if (!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 32)) {
+    die("Failed to allocate image", width, height);
+  }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+  // Populate encoder configuration.
+  res = vpx_codec_enc_config_default(encoder->codec_interface(), &cfg, 0);
+  if (res) {
+    printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
+    return EXIT_FAILURE;
+  }
+
+  // Update the default configuration with our settings.
+  cfg.g_w = width;
+  cfg.g_h = height;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+  if (bit_depth != VPX_BITS_8) {
+    cfg.g_bit_depth = bit_depth;
+    cfg.g_input_bit_depth = input_bit_depth;
+    cfg.g_profile = 2;
+  }
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+  // Timebase format e.g. 30fps: numerator=1, demoninator = 30.
+  cfg.g_timebase.num = strtol(argv[6], NULL, 0);
+  cfg.g_timebase.den = strtol(argv[7], NULL, 0);
+
+  speed = strtol(argv[8], NULL, 0);
+  if (speed < 0) {
+    die("Invalid speed setting: must be positive");
+  }
+
+  for (i = min_args_base;
+       (int)i < min_args_base + mode_to_num_layers[layering_mode];
+       ++i) {
+    rc.layer_target_bitrate[i - 11] = strtol(argv[i], NULL, 0);
+    if (strncmp(encoder->name, "vp8", 3) == 0)
+      cfg.ts_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
+    else if (strncmp(encoder->name, "vp9", 3) == 0)
+      cfg.layer_target_bitrate[i - 11] = rc.layer_target_bitrate[i - 11];
+  }
+
+  // Real time parameters.
+  cfg.rc_dropframe_thresh = strtol(argv[9], NULL, 0);
+  cfg.rc_end_usage = VPX_CBR;
+  cfg.rc_min_quantizer = 2;
+  cfg.rc_max_quantizer = 56;
+  if (strncmp(encoder->name, "vp9", 3) == 0)
+    cfg.rc_max_quantizer = 52;
+  cfg.rc_undershoot_pct = 50;
+  cfg.rc_overshoot_pct = 50;
+  cfg.rc_buf_initial_sz = 500;
+  cfg.rc_buf_optimal_sz = 600;
+  cfg.rc_buf_sz = 1000;
+
+  // Disable dynamic resizing by default.
+  cfg.rc_resize_allowed = 0;
+
+  // Use 1 thread as default.
+  cfg.g_threads = 1;
+
+  // Enable error resilient mode.
+  cfg.g_error_resilient = 1;
+  cfg.g_lag_in_frames   = 0;
+  cfg.kf_mode = VPX_KF_AUTO;
+
+  // Disable automatic keyframe placement.
+  cfg.kf_min_dist = cfg.kf_max_dist = 3000;
+
+  cfg.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+  set_temporal_layer_pattern(layering_mode,
+                             &cfg,
+                             layer_flags,
+                             &flag_periodicity);
+
+  set_rate_control_metrics(&rc, &cfg);
+
+  // Target bandwidth for the whole stream.
+  // Set to layer_target_bitrate for highest layer (total bitrate).
+  cfg.rc_target_bitrate = rc.layer_target_bitrate[cfg.ts_number_layers - 1];
+
+  // Open input file.
+  if (!(infile = fopen(argv[1], "rb"))) {
+    die("Failed to open %s for reading", argv[1]);
+  }
+
+  framerate = cfg.g_timebase.den / cfg.g_timebase.num;
+  // Open an output file for each stream.
+  for (i = 0; i < cfg.ts_number_layers; ++i) {
+    char file_name[PATH_MAX];
+    VpxVideoInfo info;
+    info.codec_fourcc = encoder->fourcc;
+    info.frame_width = cfg.g_w;
+    info.frame_height = cfg.g_h;
+    info.time_base.numerator = cfg.g_timebase.num;
+    info.time_base.denominator = cfg.g_timebase.den;
+
+    snprintf(file_name, sizeof(file_name), "%s_%d.ivf", argv[2], i);
+    outfile[i] = vpx_video_writer_open(file_name, kContainerIVF, &info);
+    if (!outfile[i])
+      die("Failed to open %s for writing", file_name);
+
+    assert(outfile[i] != NULL);
+  }
+  // No spatial layers in this encoder.
+  cfg.ss_number_layers = 1;
+
+  // Initialize codec.
+#if CONFIG_VP9_HIGHBITDEPTH
+  if (vpx_codec_enc_init(
+          &codec, encoder->codec_interface(), &cfg,
+          bit_depth == VPX_BITS_8 ? 0 : VPX_CODEC_USE_HIGHBITDEPTH))
+#else
+  if (vpx_codec_enc_init(&codec, encoder->codec_interface(), &cfg, 0))
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    die_codec(&codec, "Failed to initialize encoder");
+
+  if (strncmp(encoder->name, "vp8", 3) == 0) {
+    vpx_codec_control(&codec, VP8E_SET_CPUUSED, -speed);
+    vpx_codec_control(&codec, VP8E_SET_NOISE_SENSITIVITY, kDenoiserOff);
+    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
+  } else if (strncmp(encoder->name, "vp9", 3) == 0) {
+    vpx_svc_extra_cfg_t svc_params;
+    vpx_codec_control(&codec, VP8E_SET_CPUUSED, speed);
+    vpx_codec_control(&codec, VP9E_SET_AQ_MODE, 3);
+    vpx_codec_control(&codec, VP9E_SET_FRAME_PERIODIC_BOOST, 0);
+    vpx_codec_control(&codec, VP9E_SET_NOISE_SENSITIVITY, kDenoiserOff);
+    vpx_codec_control(&codec, VP8E_SET_STATIC_THRESHOLD, 1);
+    vpx_codec_control(&codec, VP9E_SET_TUNE_CONTENT, 0);
+    vpx_codec_control(&codec, VP9E_SET_TILE_COLUMNS, (cfg.g_threads >> 1));
+    if (vpx_codec_control(&codec, VP9E_SET_SVC, layering_mode > 0 ? 1: 0))
+      die_codec(&codec, "Failed to set SVC");
+    for (i = 0; i < cfg.ts_number_layers; ++i) {
+      svc_params.max_quantizers[i] = cfg.rc_max_quantizer;
+      svc_params.min_quantizers[i] = cfg.rc_min_quantizer;
+    }
+    svc_params.scaling_factor_num[0] = cfg.g_h;
+    svc_params.scaling_factor_den[0] = cfg.g_h;
+    vpx_codec_control(&codec, VP9E_SET_SVC_PARAMETERS, &svc_params);
+  }
+  if (strncmp(encoder->name, "vp8", 3) == 0) {
+    vpx_codec_control(&codec, VP8E_SET_SCREEN_CONTENT_MODE, 0);
+  }
+  vpx_codec_control(&codec, VP8E_SET_TOKEN_PARTITIONS, 1);
+  // This controls the maximum target size of the key frame.
+  // For generating smaller key frames, use a smaller max_intra_size_pct
+  // value, like 100 or 200.
+  {
+    const int max_intra_size_pct = 900;
+    vpx_codec_control(&codec, VP8E_SET_MAX_INTRA_BITRATE_PCT,
+                      max_intra_size_pct);
+  }
+
+  frame_avail = 1;
+  while (frame_avail || got_data) {
+    struct vpx_usec_timer timer;
+    vpx_codec_iter_t iter = NULL;
+    const vpx_codec_cx_pkt_t *pkt;
+#if VPX_ENCODER_ABI_VERSION > (4 + VPX_CODEC_ABI_VERSION)
+    // Update the temporal layer_id. No spatial layers in this test.
+    layer_id.spatial_layer_id = 0;
+#endif
+    layer_id.temporal_layer_id =
+        cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
+    if (strncmp(encoder->name, "vp9", 3) == 0) {
+      vpx_codec_control(&codec, VP9E_SET_SVC_LAYER_ID, &layer_id);
+    } else if (strncmp(encoder->name, "vp8", 3) == 0) {
+      vpx_codec_control(&codec, VP8E_SET_TEMPORAL_LAYER_ID,
+                        layer_id.temporal_layer_id);
+    }
+    flags = layer_flags[frame_cnt % flag_periodicity];
+    if (layering_mode == 0)
+      flags = 0;
+    frame_avail = vpx_img_read(&raw, infile);
+    if (frame_avail)
+      ++rc.layer_input_frames[layer_id.temporal_layer_id];
+    vpx_usec_timer_start(&timer);
+    if (vpx_codec_encode(&codec, frame_avail? &raw : NULL, pts, 1, flags,
+        VPX_DL_REALTIME)) {
+      die_codec(&codec, "Failed to encode frame");
+    }
+    vpx_usec_timer_mark(&timer);
+    cx_time += vpx_usec_timer_elapsed(&timer);
+    // Reset KF flag.
+    if (layering_mode != 7) {
+      layer_flags[0] &= ~VPX_EFLAG_FORCE_KF;
+    }
+    got_data = 0;
+    while ( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
+      got_data = 1;
+      switch (pkt->kind) {
+        case VPX_CODEC_CX_FRAME_PKT:
+          for (i = cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity];
+              i < cfg.ts_number_layers; ++i) {
+            vpx_video_writer_write_frame(outfile[i], pkt->data.frame.buf,
+                                         pkt->data.frame.sz, pts);
+            ++rc.layer_tot_enc_frames[i];
+            rc.layer_encoding_bitrate[i] += 8.0 * pkt->data.frame.sz;
+            // Keep count of rate control stats per layer (for non-key frames).
+            if (i == cfg.ts_layer_id[frame_cnt % cfg.ts_periodicity] &&
+                !(pkt->data.frame.flags & VPX_FRAME_IS_KEY)) {
+              rc.layer_avg_frame_size[i] += 8.0 * pkt->data.frame.sz;
+              rc.layer_avg_rate_mismatch[i] +=
+                  fabs(8.0 * pkt->data.frame.sz - rc.layer_pfb[i]) /
+                  rc.layer_pfb[i];
+              ++rc.layer_enc_frames[i];
+            }
+          }
+          // Update for short-time encoding bitrate states, for moving window
+          // of size rc->window, shifted by rc->window / 2.
+          // Ignore first window segment, due to key frame.
+          if (frame_cnt > rc.window_size) {
+            sum_bitrate += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
+            if (frame_cnt % rc.window_size == 0) {
+              rc.window_count += 1;
+              rc.avg_st_encoding_bitrate += sum_bitrate / rc.window_size;
+              rc.variance_st_encoding_bitrate +=
+                  (sum_bitrate / rc.window_size) *
+                  (sum_bitrate / rc.window_size);
+              sum_bitrate = 0.0;
+            }
+          }
+          // Second shifted window.
+          if (frame_cnt > rc.window_size + rc.window_size / 2) {
+            sum_bitrate2 += 0.001 * 8.0 * pkt->data.frame.sz * framerate;
+            if (frame_cnt > 2 * rc.window_size &&
+                frame_cnt % rc.window_size == 0) {
+              rc.window_count += 1;
+              rc.avg_st_encoding_bitrate += sum_bitrate2 / rc.window_size;
+              rc.variance_st_encoding_bitrate +=
+                  (sum_bitrate2 / rc.window_size) *
+                  (sum_bitrate2 / rc.window_size);
+              sum_bitrate2 = 0.0;
+            }
+          }
+          break;
+          default:
+            break;
+      }
+    }
+    ++frame_cnt;
+    pts += frame_duration;
+  }
+  fclose(infile);
+  printout_rate_control_summary(&rc, &cfg, frame_cnt);
+  printf("\n");
+  printf("Frame cnt and encoding time/FPS stats for encoding: %d %f %f \n",
+          frame_cnt,
+          1000 * (float)cx_time / (double)(frame_cnt * 1000000),
+          1000000 * (double)frame_cnt / (double)cx_time);
+
+  if (vpx_codec_destroy(&codec))
+    die_codec(&codec, "Failed to destroy codec");
+
+  // Try to rewrite the output file headers with the actual frame count.
+  for (i = 0; i < cfg.ts_number_layers; ++i)
+    vpx_video_writer_close(outfile[i]);
+
+  vpx_img_free(&raw);
+  return EXIT_SUCCESS;
+}
diff --git a/src/third_party/libvpx/fix_orbis_deps.py b/src/third_party/libvpx/fix_orbis_deps.py
new file mode 100644
index 0000000..64abfda
--- /dev/null
+++ b/src/third_party/libvpx/fix_orbis_deps.py
@@ -0,0 +1,27 @@
+import re

+import sys

+

+abs_path_re = re.compile('[A-Za-z]:\\.*')

+

+contents = sys.stdin.readlines()

+if contents:

+  contents = [line.rstrip() for line in contents]

+  contents = [line.replace('"', '') for line in contents]

+  _, first_dep_line = contents[0].split(':', 1)

+  deps = []

+  remaining_deps = [first_dep_line] + contents[1:]

+  # Go through each line and split on whitespace.

+  # There may be multiple deps on each line.

+  for line in remaining_deps:

+    line = line.strip(' \t\\')

+    line = line.replace('\\', '/')

+    line_deps = line.split()

+    deps.extend(line_deps)

+

+  # Strip out all absolute paths. Assume these are system includes

+  # we don't care about. colons in the path confuse make.

+  deps = filter(lambda d: not abs_path_re.match(d), deps)

+

+  sys.stdout.write('%s %s: \\\n' % (deps[0] + '.d', deps[0] + '.o'))

+  sys.stdout.write(' \\\n'.join([' %s' % d for d in deps]))

+  sys.stdout.write('\n')

diff --git a/src/third_party/libvpx/ivfdec.c b/src/third_party/libvpx/ivfdec.c
new file mode 100644
index 0000000..7fc25a0
--- /dev/null
+++ b/src/third_party/libvpx/ivfdec.c
@@ -0,0 +1,112 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 "vpx_ports/mem_ops.h"
+
+#include "./ivfdec.h"
+
+static const char *IVF_SIGNATURE = "DKIF";
+
+static void fix_framerate(int *num, int *den) {
+  // Some versions of vpxenc used 1/(2*fps) for the timebase, so
+  // we can guess the framerate using only the timebase in this
+  // case. Other files would require reading ahead to guess the
+  // timebase, like we do for webm.
+  if (*den > 0 && *den < 1000000000 && *num > 0 && *num < 1000) {
+    // Correct for the factor of 2 applied to the timebase in the encoder.
+    if (*num & 1)
+      *den *= 2;
+    else
+      *num /= 2;
+  } else {
+    // Don't know FPS for sure, and don't have readahead code
+    // (yet?), so just default to 30fps.
+    *num = 30;
+    *den = 1;
+  }
+}
+
+int file_is_ivf(struct VpxInputContext *input_ctx) {
+  char raw_hdr[32];
+  int is_ivf = 0;
+
+  if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
+    if (memcmp(IVF_SIGNATURE, raw_hdr, 4) == 0) {
+      is_ivf = 1;
+
+      if (mem_get_le16(raw_hdr + 4) != 0) {
+        fprintf(stderr, "Error: Unrecognized IVF version! This file may not"
+                " decode properly.");
+      }
+
+      input_ctx->fourcc = mem_get_le32(raw_hdr + 8);
+      input_ctx->width = mem_get_le16(raw_hdr + 12);
+      input_ctx->height = mem_get_le16(raw_hdr + 14);
+      input_ctx->framerate.numerator = mem_get_le32(raw_hdr + 16);
+      input_ctx->framerate.denominator = mem_get_le32(raw_hdr + 20);
+      fix_framerate(&input_ctx->framerate.numerator,
+                    &input_ctx->framerate.denominator);
+    }
+  }
+
+  if (!is_ivf) {
+    rewind(input_ctx->file);
+    input_ctx->detect.buf_read = 0;
+  } else {
+    input_ctx->detect.position = 4;
+  }
+  return is_ivf;
+}
+
+int ivf_read_frame(FILE *infile, uint8_t **buffer,
+                   size_t *bytes_read, size_t *buffer_size) {
+  char raw_header[IVF_FRAME_HDR_SZ] = {0};
+  size_t frame_size = 0;
+
+  if (fread(raw_header, IVF_FRAME_HDR_SZ, 1, infile) != 1) {
+    if (!feof(infile))
+      warn("Failed to read frame size\n");
+  } else {
+    frame_size = mem_get_le32(raw_header);
+
+    if (frame_size > 256 * 1024 * 1024) {
+      warn("Read invalid frame size (%u)\n", (unsigned int)frame_size);
+      frame_size = 0;
+    }
+
+    if (frame_size > *buffer_size) {
+      uint8_t *new_buffer = realloc(*buffer, 2 * frame_size);
+
+      if (new_buffer) {
+        *buffer = new_buffer;
+        *buffer_size = 2 * frame_size;
+      } else {
+        warn("Failed to allocate compressed data buffer\n");
+        frame_size = 0;
+      }
+    }
+  }
+
+  if (!feof(infile)) {
+    if (fread(*buffer, 1, frame_size, infile) != frame_size) {
+      warn("Failed to read full frame\n");
+      return 1;
+    }
+
+    *bytes_read = frame_size;
+    return 0;
+  }
+
+  return 1;
+}
diff --git a/src/third_party/libvpx/ivfdec.h b/src/third_party/libvpx/ivfdec.h
new file mode 100644
index 0000000..dd29cc6
--- /dev/null
+++ b/src/third_party/libvpx/ivfdec.h
@@ -0,0 +1,28 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 IVFDEC_H_
+#define IVFDEC_H_
+
+#include "./tools_common.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int file_is_ivf(struct VpxInputContext *input);
+
+int ivf_read_frame(FILE *infile, uint8_t **buffer,
+                   size_t *bytes_read, size_t *buffer_size);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  // IVFDEC_H_
diff --git a/src/third_party/libvpx/ivfenc.c b/src/third_party/libvpx/ivfenc.c
new file mode 100644
index 0000000..4a97c42
--- /dev/null
+++ b/src/third_party/libvpx/ivfenc.c
@@ -0,0 +1,53 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 "./ivfenc.h"
+
+#include "vpx/vpx_encoder.h"
+#include "vpx_ports/mem_ops.h"
+
+void ivf_write_file_header(FILE *outfile,
+                           const struct vpx_codec_enc_cfg *cfg,
+                           unsigned int fourcc,
+                           int frame_cnt) {
+  char header[32];
+
+  header[0] = 'D';
+  header[1] = 'K';
+  header[2] = 'I';
+  header[3] = 'F';
+  mem_put_le16(header + 4, 0);                     // version
+  mem_put_le16(header + 6, 32);                    // header size
+  mem_put_le32(header + 8, fourcc);                // fourcc
+  mem_put_le16(header + 12, cfg->g_w);             // width
+  mem_put_le16(header + 14, cfg->g_h);             // height
+  mem_put_le32(header + 16, cfg->g_timebase.den);  // rate
+  mem_put_le32(header + 20, cfg->g_timebase.num);  // scale
+  mem_put_le32(header + 24, frame_cnt);            // length
+  mem_put_le32(header + 28, 0);                    // unused
+
+  fwrite(header, 1, 32, outfile);
+}
+
+void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size) {
+  char header[12];
+
+  mem_put_le32(header, (int)frame_size);
+  mem_put_le32(header + 4, (int)(pts & 0xFFFFFFFF));
+  mem_put_le32(header + 8, (int)(pts >> 32));
+  fwrite(header, 1, 12, outfile);
+}
+
+void ivf_write_frame_size(FILE *outfile, size_t frame_size) {
+  char header[4];
+
+  mem_put_le32(header, (int)frame_size);
+  fwrite(header, 1, 4, outfile);
+}
diff --git a/src/third_party/libvpx/ivfenc.h b/src/third_party/libvpx/ivfenc.h
new file mode 100644
index 0000000..6623687
--- /dev/null
+++ b/src/third_party/libvpx/ivfenc.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 IVFENC_H_
+#define IVFENC_H_
+
+#include "./tools_common.h"
+
+struct vpx_codec_enc_cfg;
+struct vpx_codec_cx_pkt;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ivf_write_file_header(FILE *outfile,
+                           const struct vpx_codec_enc_cfg *cfg,
+                           uint32_t fourcc,
+                           int frame_cnt);
+
+void ivf_write_frame_header(FILE *outfile, int64_t pts, size_t frame_size);
+
+void ivf_write_frame_size(FILE *outfile, size_t frame_size);
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif  // IVFENC_H_
diff --git a/src/third_party/libvpx/keywords.dox b/src/third_party/libvpx/keywords.dox
new file mode 100644
index 0000000..56f5368
--- /dev/null
+++ b/src/third_party/libvpx/keywords.dox
@@ -0,0 +1,51 @@
+/*!\page rfc2119 RFC2119 Keywords
+
+      The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL
+      NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED",  "MAY", and
+      "OPTIONAL" in this document are to be interpreted as described in
+      <a href="http://www.ietf.org/rfc/rfc2119.txt">RFC 2119.</a>
+
+Specifically, the following definitions are used:
+
+\section MUST
+\anchor REQUIRED
+\anchor SHALL
+   This word, or the terms "REQUIRED" or "SHALL", mean that the
+   definition is an absolute requirement of the specification.
+
+\section MUSTNOT MUST NOT
+\anchor SHALLNOT
+   This phrase, or the phrase "SHALL NOT", mean that the
+   definition is an absolute prohibition of the specification.
+
+\section SHOULD
+\anchor RECOMMENDED
+   This word, or the adjective "RECOMMENDED", mean that there
+   may exist valid reasons in particular circumstances to ignore a
+   particular item, but the full implications must be understood and
+   carefully weighed before choosing a different course.
+
+\section SHOULDNOT SHOULD NOT
+\anchor NOTRECOMMENDED
+   This phrase, or the phrase "NOT RECOMMENDED" mean that
+   there may exist valid reasons in particular circumstances when the
+   particular behavior is acceptable or even useful, but the full
+   implications should be understood and the case carefully weighed
+   before implementing any behavior described with this label.
+
+\section MAY
+\anchor OPTIONAL
+   This word, or the adjective "OPTIONAL", mean that an item is
+   truly optional.  One vendor may choose to include the item because a
+   particular marketplace requires it or because the vendor feels that
+   it enhances the product while another vendor may omit the same item.
+   An implementation which does not include a particular option \ref MUST be
+   prepared to interoperate with another implementation which does
+   include the option, though perhaps with reduced functionality. In the
+   same vein an implementation which does include a particular option
+   \ref MUST be prepared to interoperate with another implementation which
+   does not include the option (except, of course, for the feature the
+   option provides.)
+
+
+*/
diff --git a/src/third_party/libvpx/libs.doxy_template b/src/third_party/libvpx/libs.doxy_template
new file mode 100644
index 0000000..5a8f847
--- /dev/null
+++ b/src/third_party/libvpx/libs.doxy_template
@@ -0,0 +1,1296 @@
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+# Doxyfile 1.5.4
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = "WebM Codec SDK"
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to java_doc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a java_doc-style
+# comment as the brief description. If set to NO, the java_doc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the defqault) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct (or union) is
+# documented as struct with the name of the typedef. So
+# typedef struct type_s {} type_t, will appear in the documentation as a struct
+# with name type_t. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named type_s. This can typically
+# be useful for C code where the coding convention is that all structs are
+# typedef'ed and only the typedef is referenced never the struct's name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be extracted
+# and appear in the documentation as a namespace called 'anonymous_namespace{file}',
+# where file will be replaced with the base name of the file that contains the anonymous
+# namespace. By default anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.  Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.  The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO. If you have enabled CALL_GRAPH or CALLER_GRAPH
+# then you must also enable this option. If you don't then doxygen will produce
+# a warning and turn it on anyway
+
+SOURCE_BROWSER         = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.  Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# java_script and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# java_script, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW      = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the la_te_x output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the la_te_x docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the la_te_x command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for la_te_x. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# la_te_x documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of la_te_x
+# packages that should be included in the la_te_x output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal la_te_x header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the la_te_x that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated la_te_x files. This will instruct la_te_x to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the auto_gen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an auto_gen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and la_te_x code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.  This is useful
+# if you want to understand what is going on.  On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  = *.h
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#   TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#   TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and la_te_x) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH             = NO
+
+# If the CALLER_GRAPH, SOURCE_BROWSER and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH           = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the number
+# of direct children of the root node in a graph is already larger than
+# MAX_DOT_GRAPH_NOTES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT        = YES
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/src/third_party/libvpx/libs.mk b/src/third_party/libvpx/libs.mk
new file mode 100644
index 0000000..f563bd3
--- /dev/null
+++ b/src/third_party/libvpx/libs.mk
@@ -0,0 +1,649 @@
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+
+# ARM assembly files are written in RVCT-style. We use some make magic to
+# filter those files to allow GCC compilation
+ifeq ($(ARCH_ARM),yes)
+  ASM:=$(if $(filter yes,$(CONFIG_GCC)$(CONFIG_MSVS)),.asm.s,.asm)
+else
+  ASM:=.asm
+endif
+
+#
+# Rule to generate runtime cpu detection files
+#
+define rtcd_h_template
+$$(BUILD_PFX)$(1).h: $$(SRC_PATH_BARE)/$(2)
+	@echo "    [CREATE] $$@"
+	$$(qexec)$$(SRC_PATH_BARE)/build/make/rtcd.pl --arch=$$(TGT_ISA) \
+          --sym=$(1) \
+          --config=$$(CONFIG_DIR)$$(target)-$$(TOOLCHAIN).mk \
+          $$(RTCD_OPTIONS) $$^ > $$@
+CLEAN-OBJS += $$(BUILD_PFX)$(1).h
+RTCD += $$(BUILD_PFX)$(1).h
+endef
+
+CODEC_SRCS-yes += CHANGELOG
+CODEC_SRCS-yes += libs.mk
+
+include $(SRC_PATH_BARE)/vpx/vpx_codec.mk
+CODEC_SRCS-yes += $(addprefix vpx/,$(call enabled,API_SRCS))
+CODEC_DOC_SRCS += $(addprefix vpx/,$(call enabled,API_DOC_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_mem/vpx_mem.mk
+CODEC_SRCS-yes += $(addprefix vpx_mem/,$(call enabled,MEM_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_scale/vpx_scale.mk
+CODEC_SRCS-yes += $(addprefix vpx_scale/,$(call enabled,SCALE_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_ports/vpx_ports.mk
+CODEC_SRCS-yes += $(addprefix vpx_ports/,$(call enabled,PORTS_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_dsp/vpx_dsp.mk
+CODEC_SRCS-yes += $(addprefix vpx_dsp/,$(call enabled,DSP_SRCS))
+
+include $(SRC_PATH_BARE)/vpx_util/vpx_util.mk
+CODEC_SRCS-yes += $(addprefix vpx_util/,$(call enabled,UTIL_SRCS))
+
+ifeq ($(CONFIG_VP8),yes)
+  VP8_PREFIX=vp8/
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8_common.mk
+endif
+
+ifeq ($(CONFIG_VP8_ENCODER),yes)
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8cx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_CX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_CX_EXPORTS))
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+  CODEC_DOC_SECTIONS += vp8 vp8_encoder
+endif
+
+ifeq ($(CONFIG_VP8_DECODER),yes)
+  include $(SRC_PATH_BARE)/$(VP8_PREFIX)vp8dx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP8_PREFIX),$(call enabled,VP8_DX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP8_PREFIX),$(VP8_DX_EXPORTS))
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP8_PREFIX)/%
+  CODEC_DOC_SECTIONS += vp8 vp8_decoder
+endif
+
+ifeq ($(CONFIG_VP9),yes)
+  VP9_PREFIX=vp9/
+  include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9_common.mk
+endif
+
+ifeq ($(CONFIG_VP9_ENCODER),yes)
+  VP9_PREFIX=vp9/
+  include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9cx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP9_PREFIX),$(call enabled,VP9_CX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_CX_EXPORTS))
+  CODEC_SRCS-yes += $(VP9_PREFIX)vp9cx.mk vpx/vp8.h vpx/vp8cx.h
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
+  INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
+  CODEC_DOC_SECTIONS += vp9 vp9_encoder
+endif
+
+ifeq ($(CONFIG_VP9_DECODER),yes)
+  VP9_PREFIX=vp9/
+  include $(SRC_PATH_BARE)/$(VP9_PREFIX)vp9dx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP9_PREFIX),$(call enabled,VP9_DX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP9_PREFIX),$(VP9_DX_EXPORTS))
+  CODEC_SRCS-yes += $(VP9_PREFIX)vp9dx.mk vpx/vp8.h vpx/vp8dx.h
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP9_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h
+  CODEC_DOC_SECTIONS += vp9 vp9_decoder
+endif
+
+VP9_PREFIX=vp9/
+$(BUILD_PFX)$(VP9_PREFIX)%.c.o: CFLAGS += -Wextra
+
+#  VP10 make file
+ifeq ($(CONFIG_VP10),yes)
+  VP10_PREFIX=vp10/
+  include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10_common.mk
+endif
+
+ifeq ($(CONFIG_VP10_ENCODER),yes)
+  VP10_PREFIX=vp10/
+  include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10cx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_CX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_CX_EXPORTS))
+  CODEC_SRCS-yes += $(VP10_PREFIX)vp10cx.mk vpx/vp8.h vpx/vp8cx.h
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8cx.h
+  INSTALL-LIBS-$(CONFIG_SPATIAL_SVC) += include/vpx/svc_context.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8cx.h
+  CODEC_DOC_SECTIONS += vp9 vp9_encoder
+endif
+
+ifeq ($(CONFIG_VP10_DECODER),yes)
+  VP10_PREFIX=vp10/
+  include $(SRC_PATH_BARE)/$(VP10_PREFIX)vp10dx.mk
+  CODEC_SRCS-yes += $(addprefix $(VP10_PREFIX),$(call enabled,VP10_DX_SRCS))
+  CODEC_EXPORTS-yes += $(addprefix $(VP10_PREFIX),$(VP10_DX_EXPORTS))
+  CODEC_SRCS-yes += $(VP10_PREFIX)vp10dx.mk vpx/vp8.h vpx/vp8dx.h
+  INSTALL-LIBS-yes += include/vpx/vp8.h include/vpx/vp8dx.h
+  INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/$(VP10_PREFIX)/%
+  CODEC_DOC_SRCS += vpx/vp8.h vpx/vp8dx.h
+  CODEC_DOC_SECTIONS += vp9 vp9_decoder
+endif
+
+VP10_PREFIX=vp10/
+$(BUILD_PFX)$(VP10_PREFIX)%.c.o: CFLAGS += -Wextra
+
+ifeq ($(CONFIG_ENCODERS),yes)
+  CODEC_DOC_SECTIONS += encoder
+endif
+ifeq ($(CONFIG_DECODERS),yes)
+  CODEC_DOC_SECTIONS += decoder
+endif
+
+
+ifeq ($(CONFIG_MSVS),yes)
+CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
+GTEST_LIB=$(if $(CONFIG_STATIC_MSVCRT),gtestmt,gtestmd)
+# This variable uses deferred expansion intentionally, since the results of
+# $(wildcard) may change during the course of the Make.
+VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
+endif
+
+# The following pairs define a mapping of locations in the distribution
+# tree to locations in the source/build trees.
+INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx/%
+INSTALL_MAPS += include/vpx/% $(SRC_PATH_BARE)/vpx_ports/%
+INSTALL_MAPS += $(LIBSUBDIR)/%     %
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+ifeq ($(CONFIG_MSVS),yes)
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/%  $(p)/Release/%)
+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/%  $(p)/Debug/%)
+endif
+
+CODEC_SRCS-yes += build/make/version.sh
+CODEC_SRCS-yes += build/make/rtcd.pl
+CODEC_SRCS-yes += vpx_ports/emmintrin_compat.h
+CODEC_SRCS-yes += vpx_ports/mem_ops.h
+CODEC_SRCS-yes += vpx_ports/mem_ops_aligned.h
+CODEC_SRCS-yes += vpx_ports/vpx_once.h
+CODEC_SRCS-yes += $(BUILD_PFX)vpx_config.c
+INSTALL-SRCS-no += $(BUILD_PFX)vpx_config.c
+ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += third_party/x86inc/x86inc.asm
+endif
+CODEC_EXPORTS-yes += vpx/exports_com
+CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_enc
+ifeq ($(CONFIG_SPATIAL_SVC),yes)
+CODEC_EXPORTS-$(CONFIG_ENCODERS) += vpx/exports_spatial_svc
+endif
+CODEC_EXPORTS-$(CONFIG_DECODERS) += vpx/exports_dec
+
+INSTALL-LIBS-yes += include/vpx/vpx_codec.h
+INSTALL-LIBS-yes += include/vpx/vpx_frame_buffer.h
+INSTALL-LIBS-yes += include/vpx/vpx_image.h
+INSTALL-LIBS-yes += include/vpx/vpx_integer.h
+INSTALL-LIBS-$(CONFIG_DECODERS) += include/vpx/vpx_decoder.h
+INSTALL-LIBS-$(CONFIG_ENCODERS) += include/vpx/vpx_encoder.h
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+INSTALL-LIBS-yes                  += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB).lib)
+INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/$(CODEC_LIB)d.lib)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.dll)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(foreach p,$(VS_PLATFORMS),$(LIBSUBDIR)/$(p)/vpx.exp)
+endif
+else
+INSTALL-LIBS-$(CONFIG_STATIC) += $(LIBSUBDIR)/libvpx.a
+INSTALL-LIBS-$(CONFIG_DEBUG_LIBS) += $(LIBSUBDIR)/libvpx_g.a
+endif
+
+CODEC_SRCS=$(call enabled,CODEC_SRCS)
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(CODEC_SRCS)
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(call enabled,CODEC_EXPORTS)
+
+
+# Generate a list of all enabled sources, in particular for exporting to gyp
+# based build systems.
+libvpx_srcs.txt:
+	@echo "    [CREATE] $@"
+	@echo $(CODEC_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
+CLEAN-OBJS += libvpx_srcs.txt
+
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+
+vpx.def: $(call enabled,CODEC_EXPORTS)
+	@echo "    [CREATE] $@"
+	$(qexec)$(SRC_PATH_BARE)/build/make/gen_msvs_def.sh\
+            --name=vpx\
+            --out=$@ $^
+CLEAN-OBJS += vpx.def
+
+# Assembly files that are included, but don't define symbols themselves.
+# Filtered out to avoid Visual Studio build warnings.
+ASM_INCLUDES := \
+    third_party/x86inc/x86inc.asm \
+    vpx_config.asm \
+    vpx_ports/x86_abi_support.asm \
+
+vpx.$(VCPROJ_SFX): $(CODEC_SRCS) vpx.def
+	@echo "    [CREATE] $@"
+	$(qexec)$(GEN_VCPROJ) \
+            $(if $(CONFIG_SHARED),--dll,--lib) \
+            --target=$(TOOLCHAIN) \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --name=vpx \
+            --proj-guid=DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74 \
+            --module-def=vpx.def \
+            --ver=$(CONFIG_VS_VERSION) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            --out=$@ $(CFLAGS) \
+            $(filter-out $(addprefix %, $(ASM_INCLUDES)), $^) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+
+PROJECTS-yes += vpx.$(VCPROJ_SFX)
+
+vpx.$(VCPROJ_SFX): vpx_config.asm
+vpx.$(VCPROJ_SFX): $(RTCD)
+
+endif
+else
+LIBVPX_OBJS=$(call objs,$(CODEC_SRCS))
+OBJS-yes += $(LIBVPX_OBJS)
+LIBS-$(if yes,$(CONFIG_STATIC)) += $(BUILD_PFX)libvpx.a $(BUILD_PFX)libvpx_g.a
+$(BUILD_PFX)libvpx_g.a: $(LIBVPX_OBJS)
+
+SO_VERSION_MAJOR := 3
+SO_VERSION_MINOR := 0
+SO_VERSION_PATCH := 0
+ifeq ($(filter darwin%,$(TGT_OS)),$(TGT_OS))
+LIBVPX_SO               := libvpx.$(SO_VERSION_MAJOR).dylib
+SHARED_LIB_SUF          := .dylib
+EXPORT_FILE             := libvpx.syms
+LIBVPX_SO_SYMLINKS      := $(addprefix $(LIBSUBDIR)/, \
+                             libvpx.dylib  )
+else
+ifeq ($(filter iphonesimulator%,$(TGT_OS)),$(TGT_OS))
+LIBVPX_SO               := libvpx.$(SO_VERSION_MAJOR).dylib
+SHARED_LIB_SUF          := .dylib
+EXPORT_FILE             := libvpx.syms
+LIBVPX_SO_SYMLINKS      := $(addprefix $(LIBSUBDIR)/, libvpx.dylib)
+else
+ifeq ($(filter os2%,$(TGT_OS)),$(TGT_OS))
+LIBVPX_SO               := libvpx$(SO_VERSION_MAJOR).dll
+SHARED_LIB_SUF          := _dll.a
+EXPORT_FILE             := libvpx.def
+LIBVPX_SO_SYMLINKS      :=
+LIBVPX_SO_IMPLIB        := libvpx_dll.a
+else
+LIBVPX_SO               := libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH)
+SHARED_LIB_SUF          := .so
+EXPORT_FILE             := libvpx.ver
+LIBVPX_SO_SYMLINKS      := $(addprefix $(LIBSUBDIR)/, \
+                             libvpx.so libvpx.so.$(SO_VERSION_MAJOR) \
+                             libvpx.so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR))
+endif
+endif
+endif
+
+LIBS-$(CONFIG_SHARED) += $(BUILD_PFX)$(LIBVPX_SO)\
+                           $(notdir $(LIBVPX_SO_SYMLINKS)) \
+                           $(if $(LIBVPX_SO_IMPLIB), $(BUILD_PFX)$(LIBVPX_SO_IMPLIB))
+$(BUILD_PFX)$(LIBVPX_SO): $(LIBVPX_OBJS) $(EXPORT_FILE)
+$(BUILD_PFX)$(LIBVPX_SO): extralibs += -lm
+$(BUILD_PFX)$(LIBVPX_SO): SONAME = libvpx.so.$(SO_VERSION_MAJOR)
+$(BUILD_PFX)$(LIBVPX_SO): EXPORTS_FILE = $(EXPORT_FILE)
+
+libvpx.ver: $(call enabled,CODEC_EXPORTS)
+	@echo "    [CREATE] $@"
+	$(qexec)echo "{ global:" > $@
+	$(qexec)for f in $?; do awk '{print $$2";"}' < $$f >>$@; done
+	$(qexec)echo "local: *; };" >> $@
+CLEAN-OBJS += libvpx.ver
+
+libvpx.syms: $(call enabled,CODEC_EXPORTS)
+	@echo "    [CREATE] $@"
+	$(qexec)awk '{print "_"$$2}' $^ >$@
+CLEAN-OBJS += libvpx.syms
+
+libvpx.def: $(call enabled,CODEC_EXPORTS)
+	@echo "    [CREATE] $@"
+	$(qexec)echo LIBRARY $(LIBVPX_SO:.dll=) INITINSTANCE TERMINSTANCE > $@
+	$(qexec)echo "DATA MULTIPLE NONSHARED" >> $@
+	$(qexec)echo "EXPORTS" >> $@
+	$(qexec)awk '!/vpx_svc_*/ {print "_"$$2}' $^ >>$@
+CLEAN-OBJS += libvpx.def
+
+libvpx_dll.a: $(LIBVPX_SO)
+	@echo "    [IMPLIB] $@"
+	$(qexec)emximp -o $@ $<
+CLEAN-OBJS += libvpx_dll.a
+
+define libvpx_symlink_template
+$(1): $(2)
+	@echo "    [LN]     $(2) $$@"
+	$(qexec)mkdir -p $$(dir $$@)
+	$(qexec)ln -sf $(2) $$@
+endef
+
+$(eval $(call libvpx_symlink_template,\
+    $(addprefix $(BUILD_PFX),$(notdir $(LIBVPX_SO_SYMLINKS))),\
+    $(BUILD_PFX)$(LIBVPX_SO)))
+$(eval $(call libvpx_symlink_template,\
+    $(addprefix $(DIST_DIR)/,$(LIBVPX_SO_SYMLINKS)),\
+    $(LIBVPX_SO)))
+
+
+INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBVPX_SO_SYMLINKS)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(LIBSUBDIR)/$(LIBVPX_SO)
+INSTALL-LIBS-$(CONFIG_SHARED) += $(if $(LIBVPX_SO_IMPLIB),$(LIBSUBDIR)/$(LIBVPX_SO_IMPLIB))
+
+
+LIBS-yes += vpx.pc
+vpx.pc: config.mk libs.mk
+	@echo "    [CREATE] $@"
+	$(qexec)echo '# pkg-config file from libvpx $(VERSION_STRING)' > $@
+	$(qexec)echo 'prefix=$(PREFIX)' >> $@
+	$(qexec)echo 'exec_prefix=$${prefix}' >> $@
+	$(qexec)echo 'libdir=$${prefix}/$(LIBSUBDIR)' >> $@
+	$(qexec)echo 'includedir=$${prefix}/include' >> $@
+	$(qexec)echo '' >> $@
+	$(qexec)echo 'Name: vpx' >> $@
+	$(qexec)echo 'Description: WebM Project VPx codec implementation' >> $@
+	$(qexec)echo 'Version: $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)' >> $@
+	$(qexec)echo 'Requires:' >> $@
+	$(qexec)echo 'Conflicts:' >> $@
+	$(qexec)echo 'Libs: -L$${libdir} -lvpx -lm' >> $@
+ifeq ($(HAVE_PTHREAD_H),yes)
+	$(qexec)echo 'Libs.private: -lm -lpthread' >> $@
+else
+	$(qexec)echo 'Libs.private: -lm' >> $@
+endif
+	$(qexec)echo 'Cflags: -I$${includedir}' >> $@
+INSTALL-LIBS-yes += $(LIBSUBDIR)/pkgconfig/vpx.pc
+INSTALL_MAPS += $(LIBSUBDIR)/pkgconfig/%.pc %.pc
+CLEAN-OBJS += vpx.pc
+endif
+
+#
+# Rule to make assembler configuration file from C configuration file
+#
+ifeq ($(ARCH_X86)$(ARCH_X86_64),yes)
+# YASM
+$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h
+	@echo "    [CREATE] $@"
+	@egrep "#define [A-Z0-9_]+ [01]" $< \
+	    | awk '{print $$2 " equ " $$3}' > $@
+else
+ADS2GAS=$(if $(filter yes,$(CONFIG_GCC)),| $(ASM_CONVERSION))
+$(BUILD_PFX)vpx_config.asm: $(BUILD_PFX)vpx_config.h
+	@echo "    [CREATE] $@"
+	@egrep "#define [A-Z0-9_]+ [01]" $< \
+	    | awk '{print $$2 " EQU " $$3}' $(ADS2GAS) > $@
+	@echo "        END" $(ADS2GAS) >> $@
+CLEAN-OBJS += $(BUILD_PFX)vpx_config.asm
+endif
+
+#
+# Add assembler dependencies for configuration.
+#
+$(filter %.s.o,$(OBJS-yes)):     $(BUILD_PFX)vpx_config.asm
+$(filter %$(ASM).o,$(OBJS-yes)): $(BUILD_PFX)vpx_config.asm
+
+
+$(shell $(SRC_PATH_BARE)/build/make/version.sh "$(SRC_PATH_BARE)" $(BUILD_PFX)vpx_version.h)
+CLEAN-OBJS += $(BUILD_PFX)vpx_version.h
+
+#
+# Add include path for libwebm sources.
+#
+ifeq ($(CONFIG_WEBM_IO),yes)
+  CXXFLAGS += -I$(SRC_PATH_BARE)/third_party/libwebm
+endif
+
+##
+## libvpx test directives
+##
+ifeq ($(CONFIG_UNIT_TESTS),yes)
+LIBVPX_TEST_DATA_PATH ?= .
+
+include $(SRC_PATH_BARE)/test/test.mk
+LIBVPX_TEST_SRCS=$(addprefix test/,$(call enabled,LIBVPX_TEST_SRCS))
+LIBVPX_TEST_BIN=./test_libvpx$(EXE_SFX)
+LIBVPX_TEST_DATA=$(addprefix $(LIBVPX_TEST_DATA_PATH)/,\
+                     $(call enabled,LIBVPX_TEST_DATA))
+libvpx_test_data_url=http://downloads.webmproject.org/test_data/libvpx/$(1)
+
+TEST_INTRA_PRED_SPEED_BIN=./test_intra_pred_speed$(EXE_SFX)
+TEST_INTRA_PRED_SPEED_SRCS=$(addprefix test/,$(call enabled,TEST_INTRA_PRED_SPEED_SRCS))
+TEST_INTRA_PRED_SPEED_OBJS := $(sort $(call objs,$(TEST_INTRA_PRED_SPEED_SRCS)))
+
+libvpx_test_srcs.txt:
+	@echo "    [CREATE] $@"
+	@echo $(LIBVPX_TEST_SRCS) | xargs -n1 echo | LC_ALL=C sort -u > $@
+CLEAN-OBJS += libvpx_test_srcs.txt
+
+$(LIBVPX_TEST_DATA): $(SRC_PATH_BARE)/test/test-data.sha1
+	@echo "    [DOWNLOAD] $@"
+	$(qexec)trap 'rm -f $@' INT TERM &&\
+            curl -L -o $@ $(call libvpx_test_data_url,$(@F))
+
+testdata:: $(LIBVPX_TEST_DATA)
+	$(qexec)[ -x "$$(which sha1sum)" ] && sha1sum=sha1sum;\
+          [ -x "$$(which shasum)" ] && sha1sum=shasum;\
+          [ -x "$$(which sha1)" ] && sha1sum=sha1;\
+          if [ -n "$${sha1sum}" ]; then\
+            set -e;\
+            echo "Checking test data:";\
+            for f in $(call enabled,LIBVPX_TEST_DATA); do\
+                grep $$f $(SRC_PATH_BARE)/test/test-data.sha1 |\
+                    (cd $(LIBVPX_TEST_DATA_PATH); $${sha1sum} -c);\
+            done; \
+        else\
+            echo "Skipping test data integrity check, sha1sum not found.";\
+        fi
+
+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
+ifeq ($(CONFIG_MSVS),yes)
+
+gtest.$(VCPROJ_SFX): $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc
+	@echo "    [CREATE] $@"
+	$(qexec)$(GEN_VCPROJ) \
+            --lib \
+            --target=$(TOOLCHAIN) \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --name=gtest \
+            --proj-guid=EC00E1EC-AF68-4D92-A255-181690D1C9B1 \
+            --ver=$(CONFIG_VS_VERSION) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            -D_VARIADIC_MAX=10 \
+            --out=gtest.$(VCPROJ_SFX) $(SRC_PATH_BARE)/third_party/googletest/src/src/gtest-all.cc \
+            -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" -I"$(SRC_PATH_BARE)/third_party/googletest/src"
+
+PROJECTS-$(CONFIG_MSVS) += gtest.$(VCPROJ_SFX)
+
+test_libvpx.$(VCPROJ_SFX): $(LIBVPX_TEST_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_SFX)
+	@echo "    [CREATE] $@"
+	$(qexec)$(GEN_VCPROJ) \
+            --exe \
+            --target=$(TOOLCHAIN) \
+            --name=test_libvpx \
+            -D_VARIADIC_MAX=10 \
+            --proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \
+            --ver=$(CONFIG_VS_VERSION) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \
+            -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \
+            $(if $(CONFIG_WEBM_IO),-I"$(SRC_PATH_BARE)/third_party/libwebm") \
+            -L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^
+
+PROJECTS-$(CONFIG_MSVS) += test_libvpx.$(VCPROJ_SFX)
+
+LIBVPX_TEST_BIN := $(addprefix $(TGT_OS:win64=x64)/Release/,$(notdir $(LIBVPX_TEST_BIN)))
+
+ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),)
+PROJECTS-$(CONFIG_MSVS) += test_intra_pred_speed.$(VCPROJ_SFX)
+test_intra_pred_speed.$(VCPROJ_SFX): $(TEST_INTRA_PRED_SPEED_SRCS) vpx.$(VCPROJ_SFX) gtest.$(VCPROJ_SFX)
+	@echo "    [CREATE] $@"
+	$(qexec)$(GEN_VCPROJ) \
+            --exe \
+            --target=$(TOOLCHAIN) \
+            --name=test_intra_pred_speed \
+            -D_VARIADIC_MAX=10 \
+            --proj-guid=CD837F5F-52D8-4314-A370-895D614166A7 \
+            --ver=$(CONFIG_VS_VERSION) \
+            --src-path-bare="$(SRC_PATH_BARE)" \
+            $(if $(CONFIG_STATIC_MSVCRT),--static-crt) \
+            --out=$@ $(INTERNAL_CFLAGS) $(CFLAGS) \
+            -I. -I"$(SRC_PATH_BARE)/third_party/googletest/src/include" \
+            -L. -l$(CODEC_LIB) -l$(GTEST_LIB) $^
+endif  # TEST_INTRA_PRED_SPEED
+endif
+else
+
+include $(SRC_PATH_BARE)/third_party/googletest/gtest.mk
+GTEST_SRCS := $(addprefix third_party/googletest/src/,$(call enabled,GTEST_SRCS))
+GTEST_OBJS=$(call objs,$(GTEST_SRCS))
+ifeq ($(filter win%,$(TGT_OS)),$(TGT_OS))
+# Disabling pthreads globally will cause issues on darwin and possibly elsewhere
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += -DGTEST_HAS_PTHREAD=0
+endif
+GTEST_INCLUDES := -I$(SRC_PATH_BARE)/third_party/googletest/src
+GTEST_INCLUDES += -I$(SRC_PATH_BARE)/third_party/googletest/src/include
+$(GTEST_OBJS) $(GTEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
+OBJS-yes += $(GTEST_OBJS)
+LIBS-yes += $(BUILD_PFX)libgtest.a $(BUILD_PFX)libgtest_g.a
+$(BUILD_PFX)libgtest_g.a: $(GTEST_OBJS)
+
+LIBVPX_TEST_OBJS=$(sort $(call objs,$(LIBVPX_TEST_SRCS)))
+$(LIBVPX_TEST_OBJS) $(LIBVPX_TEST_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
+OBJS-yes += $(LIBVPX_TEST_OBJS)
+BINS-yes += $(LIBVPX_TEST_BIN)
+
+CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
+CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a)
+TEST_LIBS := lib$(CODEC_LIB)$(CODEC_LIB_SUF) libgtest.a
+$(LIBVPX_TEST_BIN): $(TEST_LIBS)
+$(eval $(call linkerxx_template,$(LIBVPX_TEST_BIN), \
+              $(LIBVPX_TEST_OBJS) \
+              -L. -lvpx -lgtest $(extralibs) -lm))
+
+ifneq ($(strip $(TEST_INTRA_PRED_SPEED_OBJS)),)
+$(TEST_INTRA_PRED_SPEED_OBJS) $(TEST_INTRA_PRED_SPEED_OBJS:.o=.d): CXXFLAGS += $(GTEST_INCLUDES)
+OBJS-yes += $(TEST_INTRA_PRED_SPEED_OBJS)
+BINS-yes += $(TEST_INTRA_PRED_SPEED_BIN)
+
+$(TEST_INTRA_PRED_SPEED_BIN): $(TEST_LIBS)
+$(eval $(call linkerxx_template,$(TEST_INTRA_PRED_SPEED_BIN), \
+              $(TEST_INTRA_PRED_SPEED_OBJS) \
+              -L. -lvpx -lgtest $(extralibs) -lm))
+endif  # TEST_INTRA_PRED_SPEED
+
+endif  # CONFIG_UNIT_TESTS
+
+# Install test sources only if codec source is included
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(patsubst $(SRC_PATH_BARE)/%,%,\
+    $(shell find $(SRC_PATH_BARE)/third_party/googletest -type f))
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(LIBVPX_TEST_SRCS)
+INSTALL-SRCS-$(CONFIG_CODEC_SRCS) += $(TEST_INTRA_PRED_SPEED_SRCS)
+
+define test_shard_template
+test:: test_shard.$(1)
+test-no-data-check:: test_shard_ndc.$(1)
+test_shard.$(1) test_shard_ndc.$(1): $(LIBVPX_TEST_BIN)
+	@set -e; \
+	 export GTEST_SHARD_INDEX=$(1); \
+	 export GTEST_TOTAL_SHARDS=$(2); \
+	 $(LIBVPX_TEST_BIN)
+test_shard.$(1): testdata
+.PHONY: test_shard.$(1)
+endef
+
+NUM_SHARDS := 10
+SHARDS := 0 1 2 3 4 5 6 7 8 9
+$(foreach s,$(SHARDS),$(eval $(call test_shard_template,$(s),$(NUM_SHARDS))))
+
+endif
+
+##
+## documentation directives
+##
+CLEAN-OBJS += libs.doxy
+DOCS-yes += libs.doxy
+libs.doxy: $(CODEC_DOC_SRCS)
+	@echo "    [CREATE] $@"
+	@rm -f $@
+	@echo "INPUT += $^" >> $@
+	@echo "INCLUDE_PATH += ." >> $@;
+	@echo "ENABLED_SECTIONS += $(sort $(CODEC_DOC_SECTIONS))" >> $@
+
+## Generate rtcd.h for all objects
+ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes)
+$(OBJS-yes:.o=.d): $(RTCD)
+else
+$(OBJS-yes): $(RTCD)
+endif
+
+## Update the global src list
+SRCS += $(CODEC_SRCS) $(LIBVPX_TEST_SRCS) $(GTEST_SRCS)
+
+##
+## vpxdec/vpxenc tests.
+##
+ifeq ($(CONFIG_UNIT_TESTS),yes)
+TEST_BIN_PATH = .
+ifeq ($(CONFIG_MSVS),yes)
+# MSVC will build both Debug and Release configurations of tools in a
+# sub directory named for the current target. Assume the user wants to
+# run the Release tools, and assign TEST_BIN_PATH accordingly.
+# TODO(tomfinegan): Is this adequate for ARM?
+# TODO(tomfinegan): Support running the debug versions of tools?
+TEST_BIN_PATH := $(addsuffix /$(TGT_OS:win64=x64)/Release, $(TEST_BIN_PATH))
+endif
+utiltest utiltest-no-data-check:
+	$(qexec)$(SRC_PATH_BARE)/test/vpxdec.sh \
+		--test-data-path $(LIBVPX_TEST_DATA_PATH) \
+		--bin-path $(TEST_BIN_PATH)
+	$(qexec)$(SRC_PATH_BARE)/test/vpxenc.sh \
+		--test-data-path $(LIBVPX_TEST_DATA_PATH) \
+		--bin-path $(TEST_BIN_PATH)
+utiltest: testdata
+else
+utiltest utiltest-no-data-check:
+	@echo Unit tests must be enabled to make the utiltest target.
+endif
+
+##
+## Example tests.
+##
+ifeq ($(CONFIG_UNIT_TESTS),yes)
+# All non-MSVC targets output example targets in a sub dir named examples.
+EXAMPLES_BIN_PATH = examples
+ifeq ($(CONFIG_MSVS),yes)
+# MSVC will build both Debug and Release configurations of the examples in a
+# sub directory named for the current target. Assume the user wants to
+# run the Release tools, and assign EXAMPLES_BIN_PATH accordingly.
+# TODO(tomfinegan): Is this adequate for ARM?
+# TODO(tomfinegan): Support running the debug versions of tools?
+EXAMPLES_BIN_PATH := $(TGT_OS:win64=x64)/Release
+endif
+exampletest exampletest-no-data-check: examples
+	$(qexec)$(SRC_PATH_BARE)/test/examples.sh \
+		--test-data-path $(LIBVPX_TEST_DATA_PATH) \
+		--bin-path $(EXAMPLES_BIN_PATH)
+exampletest: testdata
+else
+exampletest exampletest-no-data-check:
+	@echo Unit tests must be enabled to make the exampletest target.
+endif
diff --git a/src/third_party/libvpx/libvpx.gyp b/src/third_party/libvpx/libvpx.gyp
new file mode 100644
index 0000000..d99bd16
--- /dev/null
+++ b/src/third_party/libvpx/libvpx.gyp
@@ -0,0 +1,192 @@
+{
+  'variables': {
+    'libvpx_source': '<(DEPTH)/third_party/libvpx',
+  },
+  'targets': [
+    {
+      'target_name': 'libvpx',
+      'type': 'static_library',
+      'conditions': [
+        ['target_arch == "ps4"', {
+          'variables': {
+            'use_system_yasm': '1',
+            'yasm_output_path': '<(SHARED_INTERMEDIATE_DIR)/third_party/libvpx',
+            'yasm_flags': [
+              '-f', 'elf64',
+              '-I', '<(libvpx_source)',
+              '-I', '<(libvpx_source)/platforms/<(target_arch)',
+            ],
+          },
+          'includes': [
+            '../yasm/yasm_compile.gypi'
+          ],
+          'include_dirs': [
+            '<(libvpx_source)',
+            '<(libvpx_source)/platforms/<(target_arch)',
+            '<(libvpx_source)/vpx_mem/memory_manager/include/',
+            '<(libvpx_source)/third_party/libyuv/include',
+          ],
+          # Always optimize libvpx at O3.
+          # Debug performance is too slow.
+          'cflags': ['-O3'],
+          'cflags!': ['-O0', '-O2'],
+        }],
+      ],
+      # This list was generated by running configure and then
+      # make libvpx_srcs.txt
+      'sources': [
+        'platforms/ps4/vp9_rtcd.h',
+        'platforms/ps4/vpx_config.c',
+        'platforms/ps4/vpx_config.h',
+        'platforms/ps4/vpx_dsp_rtcd.h',
+        'platforms/ps4/vpx_scale_rtcd.h',
+        'platforms/ps4/vpx_version.h',
+        'vp9/common/vp9_alloccommon.c',
+        'vp9/common/vp9_alloccommon.h',
+        'vp9/common/vp9_blockd.c',
+        'vp9/common/vp9_blockd.h',
+        'vp9/common/vp9_common.h',
+        'vp9/common/vp9_common_data.c',
+        'vp9/common/vp9_common_data.h',
+        'vp9/common/vp9_debugmodes.c',
+        'vp9/common/vp9_entropy.c',
+        'vp9/common/vp9_entropy.h',
+        'vp9/common/vp9_entropymode.c',
+        'vp9/common/vp9_entropymode.h',
+        'vp9/common/vp9_entropymv.c',
+        'vp9/common/vp9_entropymv.h',
+        'vp9/common/vp9_enums.h',
+        'vp9/common/vp9_filter.c',
+        'vp9/common/vp9_filter.h',
+        'vp9/common/vp9_frame_buffers.c',
+        'vp9/common/vp9_frame_buffers.h',
+        'vp9/common/vp9_idct.c',
+        'vp9/common/vp9_idct.h',
+        'vp9/common/vp9_loopfilter.c',
+        'vp9/common/vp9_loopfilter.h',
+        'vp9/common/vp9_mv.h',
+        'vp9/common/vp9_mvref_common.c',
+        'vp9/common/vp9_mvref_common.h',
+        'vp9/common/vp9_onyxc_int.h',
+        'vp9/common/vp9_ppflags.h',
+        'vp9/common/vp9_pred_common.c',
+        'vp9/common/vp9_pred_common.h',
+        'vp9/common/vp9_quant_common.c',
+        'vp9/common/vp9_quant_common.h',
+        'vp9/common/vp9_reconinter.c',
+        'vp9/common/vp9_reconinter.h',
+        'vp9/common/vp9_reconintra.c',
+        'vp9/common/vp9_reconintra.h',
+        'vp9/common/vp9_rtcd.c',
+        'vp9/common/vp9_scale.c',
+        'vp9/common/vp9_scale.h',
+        'vp9/common/vp9_scan.c',
+        'vp9/common/vp9_scan.h',
+        'vp9/common/vp9_seg_common.c',
+        'vp9/common/vp9_seg_common.h',
+        'vp9/common/vp9_textblit.h',
+        'vp9/common/vp9_thread_common.c',
+        'vp9/common/vp9_thread_common.h',
+        'vp9/common/vp9_tile_common.c',
+        'vp9/common/vp9_tile_common.h',
+        'vp9/common/x86/vp9_idct_intrin_sse2.c',
+        'vp9/decoder/vp9_decodeframe.c',
+        'vp9/decoder/vp9_decodeframe.h',
+        'vp9/decoder/vp9_decodemv.c',
+        'vp9/decoder/vp9_decodemv.h',
+        'vp9/decoder/vp9_decoder.c',
+        'vp9/decoder/vp9_decoder.h',
+        'vp9/decoder/vp9_detokenize.c',
+        'vp9/decoder/vp9_detokenize.h',
+        'vp9/decoder/vp9_dsubexp.c',
+        'vp9/decoder/vp9_dsubexp.h',
+        'vp9/decoder/vp9_dthread.c',
+        'vp9/decoder/vp9_dthread.h',
+        'vp9/vp9_dx_iface.c',
+        'vp9/vp9_dx_iface.h',
+        'vp9/vp9_iface_common.h',
+        'vpx/internal/vpx_codec_internal.h',
+        'vpx/internal/vpx_psnr.h',
+        'vpx/src/vpx_codec.c',
+        'vpx/src/vpx_decoder.c',
+        'vpx/src/vpx_encoder.c',
+        'vpx/src/vpx_image.c',
+        'vpx/src/vpx_psnr.c',
+        'vpx/vp8.h',
+        'vpx/vp8dx.h',
+        'vpx/vpx_codec.h',
+        'vpx/vpx_decoder.h',
+        'vpx/vpx_encoder.h',
+        'vpx/vpx_frame_buffer.h',
+        'vpx/vpx_image.h',
+        'vpx/vpx_integer.h',
+        'vpx_dsp/add_noise.c',
+        'vpx_dsp/bitreader.c',
+        'vpx_dsp/bitreader.h',
+        'vpx_dsp/bitreader_buffer.c',
+        'vpx_dsp/bitreader_buffer.h',
+        'vpx_dsp/intrapred.c',
+        'vpx_dsp/inv_txfm.c',
+        'vpx_dsp/inv_txfm.h',
+        'vpx_dsp/loopfilter.c',
+        'vpx_dsp/prob.c',
+        'vpx_dsp/prob.h',
+        'vpx_dsp/txfm_common.h',
+        'vpx_dsp/variance.c',
+        'vpx_dsp/variance.h',
+        'vpx_dsp/vpx_convolve.c',
+        'vpx_dsp/vpx_convolve.h',
+        'vpx_dsp/vpx_dsp_common.h',
+        'vpx_dsp/vpx_dsp_rtcd.c',
+        'vpx_dsp/vpx_filter.h',
+        'vpx_dsp/x86/add_noise_sse2.asm',
+        'vpx_dsp/x86/convolve.h',
+        'vpx_dsp/x86/halfpix_variance_impl_sse2.asm',
+        'vpx_dsp/x86/halfpix_variance_sse2.c',
+        'vpx_dsp/x86/intrapred_sse2.asm',
+        'vpx_dsp/x86/intrapred_ssse3.asm',
+        'vpx_dsp/x86/inv_txfm_sse2.c',
+        'vpx_dsp/x86/inv_txfm_sse2.h',
+        'vpx_dsp/x86/inv_txfm_ssse3_x86_64.asm',
+        'vpx_dsp/x86/inv_wht_sse2.asm',
+        'vpx_dsp/x86/loopfilter_sse2.c',
+        'vpx_dsp/x86/ssim_opt_x86_64.asm',
+        'vpx_dsp/x86/subpel_variance_sse2.asm',
+        'vpx_dsp/x86/txfm_common_sse2.h',
+        'vpx_dsp/x86/variance_sse2.c',
+        'vpx_dsp/x86/vpx_asm_stubs.c',
+        'vpx_dsp/x86/vpx_convolve_copy_sse2.asm',
+        'vpx_dsp/x86/vpx_subpixel_8t_intrin_ssse3.c',
+        'vpx_dsp/x86/vpx_subpixel_8t_sse2.asm',
+        'vpx_dsp/x86/vpx_subpixel_8t_ssse3.asm',
+        'vpx_dsp/x86/vpx_subpixel_bilinear_sse2.asm',
+        'vpx_dsp/x86/vpx_subpixel_bilinear_ssse3.asm',
+        'vpx_mem/include/vpx_mem_intrnl.h',
+        'vpx_mem/vpx_mem.c',
+        'vpx_mem/vpx_mem.h',
+        'vpx_ports/bitops.h',
+        'vpx_ports/emmintrin_compat.h',
+        'vpx_ports/emms.asm',
+        'vpx_ports/mem.h',
+        'vpx_ports/mem_ops.h',
+        'vpx_ports/mem_ops_aligned.h',
+        'vpx_ports/msvc.h',
+        'vpx_ports/system_state.h',
+        'vpx_ports/vpx_once.h',
+        'vpx_ports/vpx_timer.h',
+        'vpx_ports/x86.h',
+        'vpx_ports/x86_abi_support.asm',
+        'vpx_scale/generic/gen_scalers.c',
+        'vpx_scale/generic/vpx_scale.c',
+        'vpx_scale/generic/yv12config.c',
+        'vpx_scale/generic/yv12extend.c',
+        'vpx_scale/vpx_scale.h',
+        'vpx_scale/vpx_scale_rtcd.c',
+        'vpx_scale/yv12config.h',
+        'vpx_util/endian_inl.h',
+        'vpx_util/vpx_thread.c',
+        'vpx_util/vpx_thread.h',
+      ],
+    },
+  ],
+}
diff --git a/src/third_party/libvpx/mainpage.dox b/src/third_party/libvpx/mainpage.dox
new file mode 100644
index 0000000..ec202fa
--- /dev/null
+++ b/src/third_party/libvpx/mainpage.dox
@@ -0,0 +1,53 @@
+/*!\mainpage WebM Codec SDK
+
+  \section main_contents Page Contents
+  - \ref main_intro
+  - \ref main_startpoints
+  - \ref main_support
+
+  \section main_intro Introduction
+  Welcome to the WebM Codec SDK. This SDK allows you to integrate your
+  applications with the VP8 and VP9 video codecs, high quality, royalty free,
+  open source codecs deployed on billions of computers and devices worldwide.
+
+  This distribution of the WebM Codec SDK includes the following support:
+
+  \if vp8_encoder
+  - \ref vp8_encoder
+  \endif
+  \if vp8_decoder
+  - \ref vp8_decoder
+  \endif
+
+
+  \section main_startpoints Starting Points
+  - Consult the \ref changelog for a complete list of improvements in this
+    release.
+  - The \ref readme contains instructions on recompiling the sample applications.
+  - Read the \ref usage "usage" for a narrative on codec usage.
+  - Read the \ref samples "sample code" for examples of how to interact with the
+    codec.
+  - \ref codec reference
+  \if encoder
+  - \ref encoder reference
+  \endif
+  \if decoder
+  - \ref decoder reference
+  \endif
+
+  \section main_support Support Options & FAQ
+  The WebM project is an open source project supported by its community. For
+  questions about this SDK, please mail the apps-devel@webmproject.org list.
+  To contribute, see http://www.webmproject.org/code/contribute and mail
+  codec-devel@webmproject.org.
+*/
+
+/*!\page changelog CHANGELOG
+   \verbinclude CHANGELOG
+*/
+
+/*!\page readme README
+   \verbinclude README
+*/
+
+/*!\defgroup codecs Supported Codecs */
diff --git a/src/third_party/libvpx/md5_utils.c b/src/third_party/libvpx/md5_utils.c
new file mode 100644
index 0000000..a9b979a
--- /dev/null
+++ b/src/third_party/libvpx/md5_utils.c
@@ -0,0 +1,254 @@
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h' header
+ * definitions
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#include <string.h>   /* for memcpy() */
+
+#include "md5_utils.h"
+
+static void
+byteSwap(UWORD32 *buf, unsigned words) {
+  md5byte *p;
+
+  /* Only swap bytes for big endian machines */
+  int i = 1;
+
+  if (*(char *)&i == 1)
+    return;
+
+  p = (md5byte *)buf;
+
+  do {
+    *buf++ = (UWORD32)((unsigned)p[3] << 8 | p[2]) << 16 |
+             ((unsigned)p[1] << 8 | p[0]);
+    p += 4;
+  } while (--words);
+}
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx) {
+  ctx->buf[0] = 0x67452301;
+  ctx->buf[1] = 0xefcdab89;
+  ctx->buf[2] = 0x98badcfe;
+  ctx->buf[3] = 0x10325476;
+
+  ctx->bytes[0] = 0;
+  ctx->bytes[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, md5byte const *buf, unsigned len) {
+  UWORD32 t;
+
+  /* Update byte count */
+
+  t = ctx->bytes[0];
+
+  if ((ctx->bytes[0] = t + len) < t)
+    ctx->bytes[1]++;  /* Carry from low to high */
+
+  t = 64 - (t & 0x3f);  /* Space available in ctx->in (at least 1) */
+
+  if (t > len) {
+    memcpy((md5byte *)ctx->in + 64 - t, buf, len);
+    return;
+  }
+
+  /* First chunk is an odd size */
+  memcpy((md5byte *)ctx->in + 64 - t, buf, t);
+  byteSwap(ctx->in, 16);
+  MD5Transform(ctx->buf, ctx->in);
+  buf += t;
+  len -= t;
+
+  /* Process data in 64-byte chunks */
+  while (len >= 64) {
+    memcpy(ctx->in, buf, 64);
+    byteSwap(ctx->in, 16);
+    MD5Transform(ctx->buf, ctx->in);
+    buf += 64;
+    len -= 64;
+  }
+
+  /* Handle any remaining bytes of data. */
+  memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(md5byte digest[16], struct MD5Context *ctx) {
+  int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+  md5byte *p = (md5byte *)ctx->in + count;
+
+  /* Set the first char of padding to 0x80.  There is always room. */
+  *p++ = 0x80;
+
+  /* Bytes of padding needed to make 56 bytes (-8..55) */
+  count = 56 - 1 - count;
+
+  if (count < 0) {  /* Padding forces an extra block */
+    memset(p, 0, count + 8);
+    byteSwap(ctx->in, 16);
+    MD5Transform(ctx->buf, ctx->in);
+    p = (md5byte *)ctx->in;
+    count = 56;
+  }
+
+  memset(p, 0, count);
+  byteSwap(ctx->in, 14);
+
+  /* Append length in bits and transform */
+  ctx->in[14] = ctx->bytes[0] << 3;
+  ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+  MD5Transform(ctx->buf, ctx->in);
+
+  byteSwap(ctx->buf, 4);
+  memcpy(digest, ctx->buf, 16);
+  memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
+}
+
+#ifndef ASM_MD5
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+  (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+#if defined(__clang__) && defined(__has_attribute)
+#if __has_attribute(no_sanitize)
+#define VPX_NO_UNSIGNED_OVERFLOW_CHECK \
+  __attribute__((no_sanitize("unsigned-integer-overflow")))
+#endif
+#endif
+
+#ifndef VPX_NO_UNSIGNED_OVERFLOW_CHECK
+#define VPX_NO_UNSIGNED_OVERFLOW_CHECK
+#endif
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+VPX_NO_UNSIGNED_OVERFLOW_CHECK void
+MD5Transform(UWORD32 buf[4], UWORD32 const in[16]) {
+  register UWORD32 a, b, c, d;
+
+  a = buf[0];
+  b = buf[1];
+  c = buf[2];
+  d = buf[3];
+
+  MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+  MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+  MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+  MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+  MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+  MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+  MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+  MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+  MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+  MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+  MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+  MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+  MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+  MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+  MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+  MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+  MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+  MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+  MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+  MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+  MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+  MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+  MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+  MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+  MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+  MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+  MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+  MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+  MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+  MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+  MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+  MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+  MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+  MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+  MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+  MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+  MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+  MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+  MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+  MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+  MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+  MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+  MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+  MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+  MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+  MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+  MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+  MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+  MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+  MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+  MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+  MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+  MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+  MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+  MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+  MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+  MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+  MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+  MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+  MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+  MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+  MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+  MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+  MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+  buf[0] += a;
+  buf[1] += b;
+  buf[2] += c;
+  buf[3] += d;
+}
+
+#undef VPX_NO_UNSIGNED_OVERFLOW_CHECK
+
+#endif
diff --git a/src/third_party/libvpx/md5_utils.h b/src/third_party/libvpx/md5_utils.h
new file mode 100644
index 0000000..bd4991b
--- /dev/null
+++ b/src/third_party/libvpx/md5_utils.h
@@ -0,0 +1,49 @@
+/*
+ * This is the header file for the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ *
+ * Changed so as no longer to depend on Colin Plumb's `usual.h'
+ * header definitions
+ *  - Ian Jackson <ian@chiark.greenend.org.uk>.
+ * Still in the public domain.
+ */
+
+#ifndef MD5_UTILS_H_
+#define MD5_UTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define md5byte unsigned char
+#define UWORD32 unsigned int
+
+typedef struct MD5Context MD5Context;
+struct MD5Context {
+  UWORD32 buf[4];
+  UWORD32 bytes[2];
+  UWORD32 in[16];
+};
+
+void MD5Init(struct MD5Context *context);
+void MD5Update(struct MD5Context *context, md5byte const *buf, unsigned len);
+void MD5Final(unsigned char digest[16], struct MD5Context *context);
+void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // MD5_UTILS_H_
diff --git a/src/third_party/libvpx/rate_hist.c b/src/third_party/libvpx/rate_hist.c
new file mode 100644
index 0000000..a77222b
--- /dev/null
+++ b/src/third_party/libvpx/rate_hist.c
@@ -0,0 +1,285 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 <assert.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "./rate_hist.h"
+
+#define RATE_BINS 100
+#define HIST_BAR_MAX 40
+
+struct hist_bucket {
+  int low;
+  int high;
+  int count;
+};
+
+struct rate_hist {
+  int64_t *pts;
+  int *sz;
+  int samples;
+  int frames;
+  struct hist_bucket bucket[RATE_BINS];
+  int total;
+};
+
+struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
+                                      const vpx_rational_t *fps) {
+  int i;
+  struct rate_hist *hist = malloc(sizeof(*hist));
+
+  // Determine the number of samples in the buffer. Use the file's framerate
+  // to determine the number of frames in rc_buf_sz milliseconds, with an
+  // adjustment (5/4) to account for alt-refs
+  hist->samples = cfg->rc_buf_sz * 5 / 4 * fps->num / fps->den / 1000;
+
+  // prevent division by zero
+  if (hist->samples == 0)
+    hist->samples = 1;
+
+  hist->frames = 0;
+  hist->total = 0;
+
+  hist->pts = calloc(hist->samples, sizeof(*hist->pts));
+  hist->sz = calloc(hist->samples, sizeof(*hist->sz));
+  for (i = 0; i < RATE_BINS; i++) {
+    hist->bucket[i].low = INT_MAX;
+    hist->bucket[i].high = 0;
+    hist->bucket[i].count = 0;
+  }
+
+  return hist;
+}
+
+void destroy_rate_histogram(struct rate_hist *hist) {
+  if (hist) {
+    free(hist->pts);
+    free(hist->sz);
+    free(hist);
+  }
+}
+
+void update_rate_histogram(struct rate_hist *hist,
+                           const vpx_codec_enc_cfg_t *cfg,
+                           const vpx_codec_cx_pkt_t *pkt) {
+  int i;
+  int64_t then = 0;
+  int64_t avg_bitrate = 0;
+  int64_t sum_sz = 0;
+  const int64_t now = pkt->data.frame.pts * 1000 *
+                          (uint64_t)cfg->g_timebase.num /
+                              (uint64_t)cfg->g_timebase.den;
+
+  int idx = hist->frames++ % hist->samples;
+  hist->pts[idx] = now;
+  hist->sz[idx] = (int)pkt->data.frame.sz;
+
+  if (now < cfg->rc_buf_initial_sz)
+    return;
+
+  if (!cfg->rc_target_bitrate)
+    return;
+
+  then = now;
+
+  /* Sum the size over the past rc_buf_sz ms */
+  for (i = hist->frames; i > 0 && hist->frames - i < hist->samples; i--) {
+    const int i_idx = (i - 1) % hist->samples;
+
+    then = hist->pts[i_idx];
+    if (now - then > cfg->rc_buf_sz)
+      break;
+    sum_sz += hist->sz[i_idx];
+  }
+
+  if (now == then)
+    return;
+
+  avg_bitrate = sum_sz * 8 * 1000 / (now - then);
+  idx = (int)(avg_bitrate * (RATE_BINS / 2) / (cfg->rc_target_bitrate * 1000));
+  if (idx < 0)
+    idx = 0;
+  if (idx > RATE_BINS - 1)
+    idx = RATE_BINS - 1;
+  if (hist->bucket[idx].low > avg_bitrate)
+    hist->bucket[idx].low = (int)avg_bitrate;
+  if (hist->bucket[idx].high < avg_bitrate)
+    hist->bucket[idx].high = (int)avg_bitrate;
+  hist->bucket[idx].count++;
+  hist->total++;
+}
+
+static int merge_hist_buckets(struct hist_bucket *bucket,
+                              int max_buckets, int *num_buckets) {
+  int small_bucket = 0, merge_bucket = INT_MAX, big_bucket = 0;
+  int buckets = *num_buckets;
+  int i;
+
+  /* Find the extrema for this list of buckets */
+  big_bucket = small_bucket = 0;
+  for (i = 0; i < buckets; i++) {
+    if (bucket[i].count < bucket[small_bucket].count)
+      small_bucket = i;
+    if (bucket[i].count > bucket[big_bucket].count)
+      big_bucket = i;
+  }
+
+  /* If we have too many buckets, merge the smallest with an adjacent
+   * bucket.
+   */
+  while (buckets > max_buckets) {
+    int last_bucket = buckets - 1;
+
+    /* merge the small bucket with an adjacent one. */
+    if (small_bucket == 0)
+      merge_bucket = 1;
+    else if (small_bucket == last_bucket)
+      merge_bucket = last_bucket - 1;
+    else if (bucket[small_bucket - 1].count < bucket[small_bucket + 1].count)
+      merge_bucket = small_bucket - 1;
+    else
+      merge_bucket = small_bucket + 1;
+
+    assert(abs(merge_bucket - small_bucket) <= 1);
+    assert(small_bucket < buckets);
+    assert(big_bucket < buckets);
+    assert(merge_bucket < buckets);
+
+    if (merge_bucket < small_bucket) {
+      bucket[merge_bucket].high = bucket[small_bucket].high;
+      bucket[merge_bucket].count += bucket[small_bucket].count;
+    } else {
+      bucket[small_bucket].high = bucket[merge_bucket].high;
+      bucket[small_bucket].count += bucket[merge_bucket].count;
+      merge_bucket = small_bucket;
+    }
+
+    assert(bucket[merge_bucket].low != bucket[merge_bucket].high);
+
+    buckets--;
+
+    /* Remove the merge_bucket from the list, and find the new small
+     * and big buckets while we're at it
+     */
+    big_bucket = small_bucket = 0;
+    for (i = 0; i < buckets; i++) {
+      if (i > merge_bucket)
+        bucket[i] = bucket[i + 1];
+
+      if (bucket[i].count < bucket[small_bucket].count)
+        small_bucket = i;
+      if (bucket[i].count > bucket[big_bucket].count)
+        big_bucket = i;
+    }
+  }
+
+  *num_buckets = buckets;
+  return bucket[big_bucket].count;
+}
+
+static void show_histogram(const struct hist_bucket *bucket,
+                           int buckets, int total, int scale) {
+  const char *pat1, *pat2;
+  int i;
+
+  switch ((int)(log(bucket[buckets - 1].high) / log(10)) + 1) {
+    case 1:
+    case 2:
+      pat1 = "%4d %2s: ";
+      pat2 = "%4d-%2d: ";
+      break;
+    case 3:
+      pat1 = "%5d %3s: ";
+      pat2 = "%5d-%3d: ";
+      break;
+    case 4:
+      pat1 = "%6d %4s: ";
+      pat2 = "%6d-%4d: ";
+      break;
+    case 5:
+      pat1 = "%7d %5s: ";
+      pat2 = "%7d-%5d: ";
+      break;
+    case 6:
+      pat1 = "%8d %6s: ";
+      pat2 = "%8d-%6d: ";
+      break;
+    case 7:
+      pat1 = "%9d %7s: ";
+      pat2 = "%9d-%7d: ";
+      break;
+    default:
+      pat1 = "%12d %10s: ";
+      pat2 = "%12d-%10d: ";
+      break;
+  }
+
+  for (i = 0; i < buckets; i++) {
+    int len;
+    int j;
+    float pct;
+
+    pct = (float)(100.0 * bucket[i].count / total);
+    len = HIST_BAR_MAX * bucket[i].count / scale;
+    if (len < 1)
+      len = 1;
+    assert(len <= HIST_BAR_MAX);
+
+    if (bucket[i].low == bucket[i].high)
+      fprintf(stderr, pat1, bucket[i].low, "");
+    else
+      fprintf(stderr, pat2, bucket[i].low, bucket[i].high);
+
+    for (j = 0; j < HIST_BAR_MAX; j++)
+      fprintf(stderr, j < len ? "=" : " ");
+    fprintf(stderr, "\t%5d (%6.2f%%)\n", bucket[i].count, pct);
+  }
+}
+
+void show_q_histogram(const int counts[64], int max_buckets) {
+  struct hist_bucket bucket[64];
+  int buckets = 0;
+  int total = 0;
+  int scale;
+  int i;
+
+  for (i = 0; i < 64; i++) {
+    if (counts[i]) {
+      bucket[buckets].low = bucket[buckets].high = i;
+      bucket[buckets].count = counts[i];
+      buckets++;
+      total += counts[i];
+    }
+  }
+
+  fprintf(stderr, "\nQuantizer Selection:\n");
+  scale = merge_hist_buckets(bucket, max_buckets, &buckets);
+  show_histogram(bucket, buckets, total, scale);
+}
+
+void show_rate_histogram(struct rate_hist *hist,
+                         const vpx_codec_enc_cfg_t *cfg, int max_buckets) {
+  int i, scale;
+  int buckets = 0;
+
+  for (i = 0; i < RATE_BINS; i++) {
+    if (hist->bucket[i].low == INT_MAX)
+      continue;
+    hist->bucket[buckets++] = hist->bucket[i];
+  }
+
+  fprintf(stderr, "\nRate (over %dms window):\n", cfg->rc_buf_sz);
+  scale = merge_hist_buckets(hist->bucket, max_buckets, &buckets);
+  show_histogram(hist->bucket, buckets, hist->total, scale);
+}
diff --git a/src/third_party/libvpx/rate_hist.h b/src/third_party/libvpx/rate_hist.h
new file mode 100644
index 0000000..00a1676
--- /dev/null
+++ b/src/third_party/libvpx/rate_hist.h
@@ -0,0 +1,40 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 RATE_HIST_H_
+#define RATE_HIST_H_
+
+#include "vpx/vpx_encoder.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rate_hist;
+
+struct rate_hist *init_rate_histogram(const vpx_codec_enc_cfg_t *cfg,
+                                      const vpx_rational_t *fps);
+
+void destroy_rate_histogram(struct rate_hist *hist);
+
+void update_rate_histogram(struct rate_hist *hist,
+                           const vpx_codec_enc_cfg_t *cfg,
+                           const vpx_codec_cx_pkt_t *pkt);
+
+void show_q_histogram(const int counts[64], int max_buckets);
+
+void show_rate_histogram(struct rate_hist *hist, const vpx_codec_enc_cfg_t *cfg,
+                         int max_buckets);
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif
+
+#endif  // RATE_HIST_H_
diff --git a/src/third_party/libvpx/solution.mk b/src/third_party/libvpx/solution.mk
new file mode 100644
index 0000000..145adc0
--- /dev/null
+++ b/src/third_party/libvpx/solution.mk
@@ -0,0 +1,31 @@
+##
+##  Copyright (c) 2010 The WebM 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.
+##
+
+# libvpx reverse dependencies (targets that depend on libvpx)
+VPX_NONDEPS=$(addsuffix .$(VCPROJ_SFX),vpx gtest)
+VPX_RDEPS=$(foreach vcp,\
+              $(filter-out $(VPX_NONDEPS),$^), --dep=$(vcp:.$(VCPROJ_SFX)=):vpx)
+
+vpx.sln: $(wildcard *.$(VCPROJ_SFX))
+	@echo "    [CREATE] $@"
+	$(SRC_PATH_BARE)/build/make/gen_msvs_sln.sh \
+            $(if $(filter vpx.$(VCPROJ_SFX),$^),$(VPX_RDEPS)) \
+            --dep=test_libvpx:gtest \
+            --ver=$(CONFIG_VS_VERSION)\
+            --out=$@ $^
+vpx.sln.mk: vpx.sln
+	@true
+
+PROJECTS-yes += vpx.sln vpx.sln.mk
+-include vpx.sln.mk
+
+# Always install this file, as it is an unconditional post-build rule.
+INSTALL_MAPS += src/%     $(SRC_PATH_BARE)/%
+INSTALL-SRCS-yes            += $(target).mk
diff --git a/src/third_party/libvpx/test/acm_random.h b/src/third_party/libvpx/test/acm_random.h
new file mode 100644
index 0000000..b94b6e1
--- /dev/null
+++ b/src/third_party/libvpx/test/acm_random.h
@@ -0,0 +1,73 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_ACM_RANDOM_H_
+#define TEST_ACM_RANDOM_H_
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "vpx/vpx_integer.h"
+
+namespace libvpx_test {
+
+class ACMRandom {
+ public:
+  ACMRandom() : random_(DeterministicSeed()) {}
+
+  explicit ACMRandom(int seed) : random_(seed) {}
+
+  void Reset(int seed) {
+    random_.Reseed(seed);
+  }
+  uint16_t Rand16(void) {
+    const uint32_t value =
+        random_.Generate(testing::internal::Random::kMaxRange);
+    return (value >> 15) & 0xffff;
+  }
+
+  int16_t Rand9Signed(void) {
+    // Use 9 bits: values between 255 (0x0FF) and -256 (0x100).
+    const uint32_t value = random_.Generate(512);
+    return static_cast<int16_t>(value) - 256;
+  }
+
+  uint8_t Rand8(void) {
+    const uint32_t value =
+        random_.Generate(testing::internal::Random::kMaxRange);
+    // There's a bit more entropy in the upper bits of this implementation.
+    return (value >> 23) & 0xff;
+  }
+
+  uint8_t Rand8Extremes(void) {
+    // Returns a random value near 0 or near 255, to better exercise
+    // saturation behavior.
+    const uint8_t r = Rand8();
+    return r < 128 ? r << 4 : r >> 4;
+  }
+
+  int PseudoUniform(int range) {
+    return random_.Generate(range);
+  }
+
+  int operator()(int n) {
+    return PseudoUniform(n);
+  }
+
+  static int DeterministicSeed(void) {
+    return 0xbaba;
+  }
+
+ private:
+  testing::internal::Random random_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_ACM_RANDOM_H_
diff --git a/src/third_party/libvpx/test/active_map_refresh_test.cc b/src/third_party/libvpx/test/active_map_refresh_test.cc
new file mode 100644
index 0000000..c945661
--- /dev/null
+++ b/src/third_party/libvpx/test/active_map_refresh_test.cc
@@ -0,0 +1,127 @@
+/*
+ *  Copyright (c) 2015 The WebM 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 <algorithm>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+// Check if any pixel in a 16x16 macroblock varies between frames.
+int CheckMb(const vpx_image_t &current, const vpx_image_t &previous,
+            int mb_r, int mb_c) {
+  for (int plane = 0; plane < 3; plane++) {
+    int r = 16 * mb_r;
+    int c0 = 16 * mb_c;
+    int r_top = std::min(r + 16, static_cast<int>(current.d_h));
+    int c_top = std::min(c0 + 16, static_cast<int>(current.d_w));
+    r = std::max(r, 0);
+    c0 = std::max(c0, 0);
+    if (plane > 0 && current.x_chroma_shift) {
+      c_top = (c_top + 1) >> 1;
+      c0 >>= 1;
+    }
+    if (plane > 0 && current.y_chroma_shift) {
+      r_top = (r_top + 1) >> 1;
+      r >>= 1;
+    }
+    for (; r < r_top; ++r) {
+      for (int c = c0; c < c_top; ++c) {
+        if (current.planes[plane][current.stride[plane] * r + c] !=
+            previous.planes[plane][previous.stride[plane] * r + c])
+          return 1;
+      }
+    }
+  }
+  return 0;
+}
+
+void GenerateMap(int mb_rows, int mb_cols, const vpx_image_t &current,
+                 const vpx_image_t &previous, uint8_t *map) {
+  for (int mb_r = 0; mb_r < mb_rows; ++mb_r) {
+    for (int mb_c = 0; mb_c < mb_cols; ++mb_c) {
+      map[mb_r * mb_cols + mb_c] = CheckMb(current, previous, mb_r, mb_c);
+    }
+  }
+}
+
+const int kAqModeCyclicRefresh = 3;
+
+class ActiveMapRefreshTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  ActiveMapRefreshTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~ActiveMapRefreshTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    cpu_used_ = GET_PARAM(2);
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    ::libvpx_test::Y4mVideoSource *y4m_video =
+        static_cast<libvpx_test::Y4mVideoSource *>(video);
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+      encoder->Control(VP9E_SET_AQ_MODE, kAqModeCyclicRefresh);
+    } else if (video->frame() >= 2 && video->img()) {
+      vpx_image_t *current = video->img();
+      vpx_image_t *previous = y4m_holder_->img();
+      ASSERT_TRUE(previous != NULL);
+      vpx_active_map_t map = vpx_active_map_t();
+      const int width = static_cast<int>(current->d_w);
+      const int height = static_cast<int>(current->d_h);
+      const int mb_width = (width + 15) / 16;
+      const int mb_height = (height + 15) / 16;
+      uint8_t *active_map = new uint8_t[mb_width * mb_height];
+      GenerateMap(mb_height, mb_width, *current, *previous, active_map);
+      map.cols = mb_width;
+      map.rows = mb_height;
+      map.active_map = active_map;
+      encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+      delete[] active_map;
+    }
+    if (video->img()) {
+      y4m_video->SwapBuffers(y4m_holder_);
+    }
+  }
+
+  int cpu_used_;
+  ::libvpx_test::Y4mVideoSource *y4m_holder_;
+};
+
+TEST_P(ActiveMapRefreshTest, Test) {
+  cfg_.g_lag_in_frames = 0;
+  cfg_.g_profile = 1;
+  cfg_.rc_target_bitrate = 600;
+  cfg_.rc_resize_allowed = 0;
+  cfg_.rc_min_quantizer = 8;
+  cfg_.rc_max_quantizer = 30;
+  cfg_.g_pass = VPX_RC_ONE_PASS;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.kf_max_dist = 90000;
+
+  ::libvpx_test::Y4mVideoSource video("desktop_credits.y4m", 0, 30);
+  ::libvpx_test::Y4mVideoSource video_holder("desktop_credits.y4m", 0, 30);
+  video_holder.Begin();
+  y4m_holder_ = &video_holder;
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(ActiveMapRefreshTest,
+                          ::testing::Values(::libvpx_test::kRealTime),
+                          ::testing::Range(5, 6));
+}  // namespace
diff --git a/src/third_party/libvpx/test/active_map_test.cc b/src/third_party/libvpx/test/active_map_test.cc
new file mode 100644
index 0000000..dc3de72
--- /dev/null
+++ b/src/third_party/libvpx/test/active_map_test.cc
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class ActiveMapTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  static const int kWidth = 208;
+  static const int kHeight = 144;
+
+  ActiveMapTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~ActiveMapTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    cpu_used_ = GET_PARAM(2);
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+    } else if (video->frame() == 3) {
+      vpx_active_map_t map = vpx_active_map_t();
+      uint8_t active_map[9 * 13] = {
+        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0,
+        0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1,
+        0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1,
+        0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1,
+        0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1,
+        1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0,
+      };
+      map.cols = (kWidth + 15) / 16;
+      map.rows = (kHeight + 15) / 16;
+      ASSERT_EQ(map.cols, 13u);
+      ASSERT_EQ(map.rows, 9u);
+      map.active_map = active_map;
+      encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+    } else if (video->frame() == 15) {
+      vpx_active_map_t map = vpx_active_map_t();
+      map.cols = (kWidth + 15) / 16;
+      map.rows = (kHeight + 15) / 16;
+      map.active_map = NULL;
+      encoder->Control(VP8E_SET_ACTIVEMAP, &map);
+    }
+  }
+
+  int cpu_used_;
+};
+
+TEST_P(ActiveMapTest, Test) {
+  // Validate that this non multiple of 64 wide clip encodes
+  cfg_.g_lag_in_frames = 0;
+  cfg_.rc_target_bitrate = 400;
+  cfg_.rc_resize_allowed = 0;
+  cfg_.g_pass = VPX_RC_ONE_PASS;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.kf_max_dist = 90000;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", kWidth, kHeight, 30,
+                                       1, 0, 20);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(ActiveMapTest,
+                          ::testing::Values(::libvpx_test::kRealTime),
+                          ::testing::Range(0, 9));
+}  // namespace
diff --git a/src/third_party/libvpx/test/add_noise_test.cc b/src/third_party/libvpx/test/add_noise_test.cc
new file mode 100644
index 0000000..e9945c4
--- /dev/null
+++ b/src/third_party/libvpx/test/add_noise_test.cc
@@ -0,0 +1,197 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 <math.h>
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_dsp_rtcd.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+// TODO(jimbankoski): make width and height integers not unsigned.
+typedef void (*AddNoiseFunc)(unsigned char *start, char *noise,
+                             char blackclamp[16], char whiteclamp[16],
+                             char bothclamp[16], unsigned int width,
+                             unsigned int height, int pitch);
+
+class AddNoiseTest
+    : public ::testing::TestWithParam<AddNoiseFunc> {
+ public:
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+  virtual ~AddNoiseTest() {}
+};
+
+double stddev6(char a, char b, char c, char d, char e, char f) {
+  const double n = (a + b + c + d + e + f) / 6.0;
+  const double v = ((a - n) * (a - n) + (b - n) * (b - n) + (c - n) * (c - n) +
+                    (d - n) * (d - n) + (e - n) * (e - n) + (f - n) * (f - n)) /
+                   6.0;
+  return sqrt(v);
+}
+
+// TODO(jimbankoski): The following 2 functions are duplicated in each codec.
+// For now the vp9 one has been copied into the test as is. We should normalize
+// these in vpx_dsp and not have 3 copies of these unless there is different
+// noise we add for each codec.
+
+double gaussian(double sigma, double mu, double x) {
+  return 1 / (sigma * sqrt(2.0 * 3.14159265)) *
+         (exp(-(x - mu) * (x - mu) / (2 * sigma * sigma)));
+}
+
+int setup_noise(int size_noise, char *noise) {
+  char char_dist[300];
+  const int ai = 4;
+  const int qi = 24;
+  const double sigma = ai + .5 + .6 * (63 - qi) / 63.0;
+
+  /* set up a lookup table of 256 entries that matches
+   * a gaussian distribution with sigma determined by q.
+   */
+  int next = 0;
+
+  for (int i = -32; i < 32; i++) {
+    int a_i = (int) (0.5 + 256 * gaussian(sigma, 0, i));
+
+    if (a_i) {
+      for (int j = 0; j < a_i; j++) {
+        char_dist[next + j] = (char)(i);
+      }
+
+      next = next + a_i;
+    }
+  }
+
+  for (; next < 256; next++)
+    char_dist[next] = 0;
+
+  for (int i = 0; i < size_noise; i++) {
+    noise[i] = char_dist[rand() & 0xff];  // NOLINT
+  }
+
+  // Returns the most negative value in distribution.
+  return char_dist[0];
+}
+
+TEST_P(AddNoiseTest, CheckNoiseAdded) {
+  DECLARE_ALIGNED(16, char, blackclamp[16]);
+  DECLARE_ALIGNED(16, char, whiteclamp[16]);
+  DECLARE_ALIGNED(16, char, bothclamp[16]);
+  const int width  = 64;
+  const int height = 64;
+  const int image_size = width * height;
+  char noise[3072];
+
+  const int clamp = setup_noise(3072, noise);
+  for (int i = 0; i < 16; i++) {
+    blackclamp[i] = -clamp;
+    whiteclamp[i] = -clamp;
+    bothclamp[i] = -2 * clamp;
+  }
+
+  uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
+  memset(s, 99, image_size);
+
+  ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
+                                      bothclamp, width, height, width));
+
+  // Check to make sure we don't end up having either the same or no added
+  // noise either vertically or horizontally.
+  for (int i = 0; i < image_size - 6 * width - 6; ++i) {
+    const double hd = stddev6(s[i] - 99, s[i + 1] - 99, s[i + 2] - 99,
+                              s[i + 3] - 99, s[i + 4] - 99, s[i + 5] - 99);
+    const double vd = stddev6(s[i] - 99, s[i + width] - 99,
+                              s[i + 2 * width] - 99, s[i + 3 * width] - 99,
+                              s[i + 4 * width] - 99, s[i + 5 * width] - 99);
+
+    EXPECT_NE(hd, 0);
+    EXPECT_NE(vd, 0);
+  }
+
+  // Initialize pixels in the image to 255 and check for roll over.
+  memset(s, 255, image_size);
+
+  ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
+                                      bothclamp, width, height, width));
+
+  // Check to make sure don't roll over.
+  for (int i = 0; i < image_size; ++i) {
+    EXPECT_GT((int)s[i], 10) << "i = " << i;
+  }
+
+  // Initialize pixels in the image to 0 and check for roll under.
+  memset(s, 0, image_size);
+
+  ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
+                                      bothclamp, width, height, width));
+
+  // Check to make sure don't roll under.
+  for (int i = 0; i < image_size; ++i) {
+    EXPECT_LT((int)s[i], 245) << "i = " << i;
+  }
+
+  vpx_free(s);
+}
+
+TEST_P(AddNoiseTest, CheckCvsAssembly) {
+  DECLARE_ALIGNED(16, char, blackclamp[16]);
+  DECLARE_ALIGNED(16, char, whiteclamp[16]);
+  DECLARE_ALIGNED(16, char, bothclamp[16]);
+  const int width  = 64;
+  const int height = 64;
+  const int image_size = width * height;
+  char noise[3072];
+
+  const int clamp = setup_noise(3072, noise);
+  for (int i = 0; i < 16; i++) {
+    blackclamp[i] = -clamp;
+    whiteclamp[i] = -clamp;
+    bothclamp[i] = -2 * clamp;
+  }
+
+  uint8_t *const s = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
+  uint8_t *const d = reinterpret_cast<uint8_t *>(vpx_calloc(image_size, 1));
+
+  memset(s, 99, image_size);
+  memset(d, 99, image_size);
+
+  srand(0);
+  ASM_REGISTER_STATE_CHECK(GetParam()(s, noise, blackclamp, whiteclamp,
+                                      bothclamp, width, height, width));
+  srand(0);
+  ASM_REGISTER_STATE_CHECK(vpx_plane_add_noise_c(d, noise, blackclamp,
+                                                 whiteclamp, bothclamp,
+                                                 width, height, width));
+
+  for (int i = 0; i < image_size; ++i) {
+    EXPECT_EQ((int)s[i], (int)d[i]) << "i = " << i;
+  }
+
+  vpx_free(d);
+  vpx_free(s);
+}
+
+INSTANTIATE_TEST_CASE_P(C, AddNoiseTest,
+                        ::testing::Values(vpx_plane_add_noise_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(SSE2, AddNoiseTest,
+                        ::testing::Values(vpx_plane_add_noise_sse2));
+#endif
+
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(MSA, AddNoiseTest,
+                        ::testing::Values(vpx_plane_add_noise_msa));
+#endif
+}  // namespace
diff --git a/src/third_party/libvpx/test/altref_test.cc b/src/third_party/libvpx/test/altref_test.cc
new file mode 100644
index 0000000..0799f42
--- /dev/null
+++ b/src/third_party/libvpx/test/altref_test.cc
@@ -0,0 +1,170 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+namespace {
+
+#if CONFIG_VP8_ENCODER
+
+// lookahead range: [kLookAheadMin, kLookAheadMax).
+const int kLookAheadMin = 5;
+const int kLookAheadMax = 26;
+
+class AltRefTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<int> {
+ protected:
+  AltRefTest() : EncoderTest(GET_PARAM(0)), altref_count_(0) {}
+  virtual ~AltRefTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(libvpx_test::kTwoPassGood);
+  }
+
+  virtual void BeginPassHook(unsigned int pass) {
+    altref_count_ = 0;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      encoder->Control(VP8E_SET_CPUUSED, 3);
+    }
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) ++altref_count_;
+  }
+
+  int altref_count() const { return altref_count_; }
+
+ private:
+  int altref_count_;
+};
+
+TEST_P(AltRefTest, MonotonicTimestamps) {
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 1000;
+  cfg_.g_lag_in_frames = GET_PARAM(1);
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 30);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  EXPECT_GE(altref_count(), 1);
+}
+
+VP8_INSTANTIATE_TEST_CASE(AltRefTest,
+                          ::testing::Range(kLookAheadMin, kLookAheadMax));
+
+#endif  // CONFIG_VP8_ENCODER
+
+class AltRefForcedKeyTestLarge
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  AltRefForcedKeyTestLarge()
+      : EncoderTest(GET_PARAM(0)),
+        encoding_mode_(GET_PARAM(1)),
+        cpu_used_(GET_PARAM(2)),
+        forced_kf_frame_num_(1),
+        frame_num_(0) {}
+  virtual ~AltRefForcedKeyTestLarge() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+    cfg_.rc_end_usage = VPX_VBR;
+    cfg_.g_threads = 0;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      // override test default for tile columns if necessary.
+#if CONFIG_VP9_ENCODER
+      if (GET_PARAM(0) == &libvpx_test::kVP9) {
+        encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
+      }
+#endif
+#if CONFIG_VP10_ENCODER
+      if (GET_PARAM(0) == &libvpx_test::kVP10) {
+        encoder->Control(VP9E_SET_TILE_COLUMNS, 6);
+      }
+#endif
+    }
+    frame_flags_ =
+        (video->frame() == forced_kf_frame_num_) ? VPX_EFLAG_FORCE_KF : 0;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (frame_num_ == forced_kf_frame_num_) {
+      ASSERT_TRUE(!!(pkt->data.frame.flags & VPX_FRAME_IS_KEY))
+          << "Frame #" << frame_num_ << " isn't a keyframe!";
+    }
+    ++frame_num_;
+  }
+
+  ::libvpx_test::TestMode encoding_mode_;
+  int cpu_used_;
+  unsigned int forced_kf_frame_num_;
+  unsigned int frame_num_;
+};
+
+TEST_P(AltRefForcedKeyTestLarge, Frame1IsKey) {
+  const vpx_rational timebase = { 1, 30 };
+  const int lag_values[] = { 3, 15, 25, -1 };
+
+  forced_kf_frame_num_ = 1;
+  for (int i = 0; lag_values[i] != -1; ++i) {
+    frame_num_ = 0;
+    cfg_.g_lag_in_frames = lag_values[i];
+    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       timebase.den, timebase.num, 0, 30);
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  }
+}
+
+TEST_P(AltRefForcedKeyTestLarge, ForcedFrameIsKey) {
+  const vpx_rational timebase = { 1, 30 };
+  const int lag_values[] = { 3, 15, 25, -1 };
+
+  for (int i = 0; lag_values[i] != -1; ++i) {
+    frame_num_ = 0;
+    forced_kf_frame_num_ = lag_values[i] - 1;
+    cfg_.g_lag_in_frames = lag_values[i];
+    libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       timebase.den, timebase.num, 0, 30);
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  }
+}
+
+VP8_INSTANTIATE_TEST_CASE(
+    AltRefForcedKeyTestLarge,
+    ::testing::Values(::libvpx_test::kOnePassGood),
+    ::testing::Range(0, 9));
+
+VP9_INSTANTIATE_TEST_CASE(
+    AltRefForcedKeyTestLarge,
+    ::testing::Values(::libvpx_test::kOnePassGood),
+    ::testing::Range(0, 9));
+
+VP10_INSTANTIATE_TEST_CASE(
+    AltRefForcedKeyTestLarge,
+    ::testing::Values(::libvpx_test::kOnePassGood),
+    ::testing::Range(0, 9));
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/android/Android.mk b/src/third_party/libvpx/test/android/Android.mk
new file mode 100644
index 0000000..48872a2
--- /dev/null
+++ b/src/third_party/libvpx/test/android/Android.mk
@@ -0,0 +1,56 @@
+# Copyright (c) 2013 The WebM 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.
+#
+# This make file builds vpx_test app for android.
+# The test app itself runs on the command line through adb shell
+# The paths are really messed up as the libvpx make file
+# expects to be made from a parent directory.
+CUR_WD := $(call my-dir)
+BINDINGS_DIR := $(CUR_WD)/../../..
+LOCAL_PATH := $(CUR_WD)/../../..
+
+#libwebm
+include $(CLEAR_VARS)
+include $(BINDINGS_DIR)/libvpx/third_party/libwebm/Android.mk
+LOCAL_PATH := $(CUR_WD)/../../..
+
+#libvpx
+include $(CLEAR_VARS)
+LOCAL_STATIC_LIBRARIES := libwebm
+include $(BINDINGS_DIR)/libvpx/build/make/Android.mk
+LOCAL_PATH := $(CUR_WD)/../..
+
+#libgtest
+include $(CLEAR_VARS)
+LOCAL_ARM_MODE := arm
+LOCAL_CPP_EXTENSION := .cc
+LOCAL_MODULE := gtest
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/third_party/googletest/src/
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/third_party/googletest/src/include/
+LOCAL_SRC_FILES := ./third_party/googletest/src/src/gtest-all.cc
+include $(BUILD_STATIC_LIBRARY)
+
+#libvpx_test
+include $(CLEAR_VARS)
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE := libvpx_test
+LOCAL_STATIC_LIBRARIES := gtest libwebm
+
+ifeq ($(ENABLE_SHARED),1)
+  LOCAL_SHARED_LIBRARIES := vpx
+else
+  LOCAL_STATIC_LIBRARIES += vpx
+endif
+
+include $(LOCAL_PATH)/test/test.mk
+LOCAL_C_INCLUDES := $(BINDINGS_DIR)
+FILTERED_SRC := $(sort $(filter %.cc %.c, $(LIBVPX_TEST_SRCS-yes)))
+LOCAL_SRC_FILES := $(addprefix ./test/, $(FILTERED_SRC))
+# some test files depend on *_rtcd.h, ensure they're generated first.
+$(eval $(call rtcd_dep_template))
+include $(BUILD_EXECUTABLE)
diff --git a/src/third_party/libvpx/test/android/README b/src/third_party/libvpx/test/android/README
new file mode 100644
index 0000000..4a1adcf
--- /dev/null
+++ b/src/third_party/libvpx/test/android/README
@@ -0,0 +1,32 @@
+Android.mk will build vpx unittests on android.
+1) Configure libvpx from the parent directory:
+./libvpx/configure --target=armv7-android-gcc --enable-external-build \
+  --enable-postproc --disable-install-srcs --enable-multi-res-encoding \
+  --enable-temporal-denoising --disable-unit-tests --disable-install-docs \
+  --disable-examples --disable-runtime-cpu-detect --sdk-path=$NDK
+
+2) From the parent directory, invoke ndk-build:
+NDK_PROJECT_PATH=. ndk-build APP_BUILD_SCRIPT=./libvpx/test/android/Android.mk \
+  APP_ABI=armeabi-v7a APP_PLATFORM=android-18 APP_OPTIM=release \
+  APP_STL=gnustl_static
+
+Note: Both adb and ndk-build are available prebuilt at:
+  https://chromium.googlesource.com/android_tools
+
+3) Run get_files.py to download the test files:
+python get_files.py -i /path/to/test-data.sha1 -o /path/to/put/files \
+  -u http://downloads.webmproject.org/test_data/libvpx
+
+4) Transfer files to device using adb. Ensure you have proper permissions for
+the target
+
+adb push /path/to/test_files /data/local/tmp
+adb push /path/to/built_libs /data/local/tmp
+
+NOTE: Built_libs defaults to parent_dir/libs/armeabi-v7a
+
+5) Run tests:
+adb shell
+(on device)
+cd /data/local/tmp
+LD_LIBRARY_PATH=. ./vpx_test
diff --git a/src/third_party/libvpx/test/android/get_files.py b/src/third_party/libvpx/test/android/get_files.py
new file mode 100644
index 0000000..1c69740
--- /dev/null
+++ b/src/third_party/libvpx/test/android/get_files.py
@@ -0,0 +1,118 @@
+# Copyright (c) 2013 The WebM 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.
+#
+# This simple script pulls test files from the webm homepage
+# It is intelligent enough to only pull files if
+#   1) File / test_data folder does not exist
+#   2) SHA mismatch
+
+import pycurl
+import csv
+import hashlib
+import re
+import os.path
+import time
+import itertools
+import sys
+import getopt
+
+#globals
+url = ''
+file_list_path = ''
+local_resource_path = ''
+
+# Helper functions:
+# A simple function which returns the sha hash of a file in hex
+def get_file_sha(filename):
+  try:
+    sha_hash = hashlib.sha1()
+    with open(filename, 'rb') as file:
+      buf = file.read(HASH_CHUNK)
+      while len(buf) > 0:
+        sha_hash.update(buf)
+        buf = file.read(HASH_CHUNK)
+      return sha_hash.hexdigest()
+  except IOError:
+    print "Error reading " + filename
+
+# Downloads a file from a url, and then checks the sha against the passed
+# in sha
+def download_and_check_sha(url, filename, sha):
+  path = os.path.join(local_resource_path, filename)
+  fp = open(path, "wb")
+  curl = pycurl.Curl()
+  curl.setopt(pycurl.URL, url + "/" + filename)
+  curl.setopt(pycurl.WRITEDATA, fp)
+  curl.perform()
+  curl.close()
+  fp.close()
+  return get_file_sha(path) == sha
+
+#constants
+ftp_retries = 3
+
+SHA_COL = 0
+NAME_COL = 1
+EXPECTED_COL = 2
+HASH_CHUNK = 65536
+
+# Main script
+try:
+  opts, args = \
+      getopt.getopt(sys.argv[1:], \
+                    "u:i:o:", ["url=", "input_csv=", "output_dir="])
+except:
+  print 'get_files.py -u <url> -i <input_csv> -o <output_dir>'
+  sys.exit(2)
+
+for opt, arg in opts:
+  if opt == '-u':
+    url = arg
+  elif opt in ("-i", "--input_csv"):
+    file_list_path = os.path.join(arg)
+  elif opt in ("-o", "--output_dir"):
+    local_resource_path = os.path.join(arg)
+
+if len(sys.argv) != 7:
+  print "Expects two paths and a url!"
+  exit(1)
+
+if not os.path.isdir(local_resource_path):
+  os.makedirs(local_resource_path)
+
+file_list_csv = open(file_list_path, "rb")
+
+# Our 'csv' file uses multiple spaces as a delimiter, python's
+# csv class only uses single character delimiters, so we convert them below
+file_list_reader = csv.reader((re.sub(' +', ' ', line) \
+    for line in file_list_csv), delimiter = ' ')
+
+file_shas = []
+file_names = []
+
+for row in file_list_reader:
+  if len(row) != EXPECTED_COL:
+      continue
+  file_shas.append(row[SHA_COL])
+  file_names.append(row[NAME_COL])
+
+file_list_csv.close()
+
+# Download files, only if they don't already exist and have correct shas
+for filename, sha in itertools.izip(file_names, file_shas):
+  path = os.path.join(local_resource_path, filename)
+  if os.path.isfile(path) \
+      and get_file_sha(path) == sha:
+    print path + ' exists, skipping'
+    continue
+  for retry in range(0, ftp_retries):
+    print "Downloading " + path
+    if not download_and_check_sha(url, filename, sha):
+      print "Sha does not match, retrying..."
+    else:
+      break
diff --git a/src/third_party/libvpx/test/android/scrape_gtest_log.py b/src/third_party/libvpx/test/android/scrape_gtest_log.py
new file mode 100644
index 0000000..487845c
--- /dev/null
+++ b/src/third_party/libvpx/test/android/scrape_gtest_log.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2014 The WebM 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.
+
+"""Standalone script which parses a gtest log for json.
+
+Json is returned returns as an array.  This script is used by the libvpx
+waterfall to gather json results mixed in with gtest logs.  This is
+dubious software engineering.
+"""
+
+import getopt
+import json
+import os
+import re
+import sys
+
+
+def main():
+  if len(sys.argv) != 3:
+    print "Expects a file to write json to!"
+    exit(1)
+
+  try:
+    opts, _ = \
+        getopt.getopt(sys.argv[1:], \
+                      'o:', ['output-json='])
+  except getopt.GetOptError:
+    print 'scrape_gtest_log.py -o <output_json>'
+    sys.exit(2)
+
+  output_json = ''
+  for opt, arg in opts:
+    if opt in ('-o', '--output-json'):
+      output_json = os.path.join(arg)
+
+  blob = sys.stdin.read()
+  json_string = '[' + ','.join('{' + x + '}' for x in
+                               re.findall(r'{([^}]*.?)}', blob)) + ']'
+  print blob
+
+  output = json.dumps(json.loads(json_string), indent=4, sort_keys=True)
+  print output
+
+  path = os.path.dirname(output_json)
+  if path and not os.path.exists(path):
+    os.makedirs(path)
+
+  outfile = open(output_json, 'w')
+  outfile.write(output)
+
+if __name__ == '__main__':
+  sys.exit(main())
diff --git a/src/third_party/libvpx/test/aq_segment_test.cc b/src/third_party/libvpx/test/aq_segment_test.cc
new file mode 100644
index 0000000..1b9c943
--- /dev/null
+++ b/src/third_party/libvpx/test/aq_segment_test.cc
@@ -0,0 +1,109 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class AqSegmentTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  AqSegmentTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~AqSegmentTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    set_cpu_used_ = GET_PARAM(2);
+    aq_mode_ = 0;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+      encoder->Control(VP9E_SET_AQ_MODE, aq_mode_);
+      encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 100);
+    }
+  }
+
+  int set_cpu_used_;
+  int aq_mode_;
+};
+
+// Validate that this AQ segmentation mode (AQ=1, variance_ap)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ1) {
+  cfg_.rc_min_quantizer = 8;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_target_bitrate = 300;
+
+  aq_mode_ = 1;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                        30, 1, 0, 100);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this AQ segmentation mode (AQ=2, complexity_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ2) {
+  cfg_.rc_min_quantizer = 8;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_target_bitrate = 300;
+
+  aq_mode_ = 2;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                        30, 1, 0, 100);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+// Validate that this AQ segmentation mode (AQ=3, cyclic_refresh_aq)
+// encodes and decodes without a mismatch.
+TEST_P(AqSegmentTest, TestNoMisMatchAQ3) {
+  cfg_.rc_min_quantizer = 8;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_target_bitrate = 300;
+
+  aq_mode_ = 3;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                        30, 1, 0, 100);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(AqSegmentTest,
+                          ::testing::Values(::libvpx_test::kRealTime,
+                                            ::libvpx_test::kOnePassGood),
+                          ::testing::Range(3, 9));
+}  // namespace
diff --git a/src/third_party/libvpx/test/avg_test.cc b/src/third_party/libvpx/test/avg_test.cc
new file mode 100644
index 0000000..44d8dd7
--- /dev/null
+++ b/src/third_party/libvpx/test/avg_test.cc
@@ -0,0 +1,411 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx_mem/vpx_mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class AverageTestBase : public ::testing::Test {
+ public:
+  AverageTestBase(int width, int height) : width_(width), height_(height) {}
+
+  static void SetUpTestCase() {
+    source_data_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBlockSize));
+  }
+
+  static void TearDownTestCase() {
+    vpx_free(source_data_);
+    source_data_ = NULL;
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  // Handle blocks up to 4 blocks 64x64 with stride up to 128
+  static const int kDataAlignment = 16;
+  static const int kDataBlockSize = 64 * 128;
+
+  virtual void SetUp() {
+    source_stride_ = (width_ + 31) & ~31;
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+  // Sum Pixels
+  unsigned int ReferenceAverage8x8(const uint8_t* source, int pitch) {
+    unsigned int average = 0;
+    for (int h = 0; h < 8; ++h)
+      for (int w = 0; w < 8; ++w)
+        average += source[h * pitch + w];
+    return ((average + 32) >> 6);
+  }
+
+  unsigned int ReferenceAverage4x4(const uint8_t* source, int pitch) {
+    unsigned int average = 0;
+    for (int h = 0; h < 4; ++h)
+      for (int w = 0; w < 4; ++w)
+        average += source[h * pitch + w];
+    return ((average + 8) >> 4);
+  }
+
+  void FillConstant(uint8_t fill_constant) {
+    for (int i = 0; i < width_ * height_; ++i) {
+        source_data_[i] = fill_constant;
+    }
+  }
+
+  void FillRandom() {
+    for (int i = 0; i < width_ * height_; ++i) {
+        source_data_[i] = rnd_.Rand8();
+    }
+  }
+
+  int width_, height_;
+  static uint8_t* source_data_;
+  int source_stride_;
+
+  ACMRandom rnd_;
+};
+typedef unsigned int (*AverageFunction)(const uint8_t* s, int pitch);
+
+typedef std::tr1::tuple<int, int, int, int, AverageFunction> AvgFunc;
+
+class AverageTest
+    : public AverageTestBase,
+      public ::testing::WithParamInterface<AvgFunc>{
+ public:
+  AverageTest() : AverageTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+  void CheckAverages() {
+    unsigned int expected = 0;
+    if (GET_PARAM(3) == 8) {
+      expected = ReferenceAverage8x8(source_data_+ GET_PARAM(2),
+                                     source_stride_);
+    } else  if (GET_PARAM(3) == 4) {
+      expected = ReferenceAverage4x4(source_data_+ GET_PARAM(2),
+                                     source_stride_);
+    }
+
+    ASM_REGISTER_STATE_CHECK(GET_PARAM(4)(source_data_+ GET_PARAM(2),
+                                          source_stride_));
+    unsigned int actual = GET_PARAM(4)(source_data_+ GET_PARAM(2),
+                                       source_stride_);
+
+    EXPECT_EQ(expected, actual);
+  }
+};
+
+typedef void (*IntProRowFunc)(int16_t hbuf[16], uint8_t const *ref,
+                              const int ref_stride, const int height);
+
+typedef std::tr1::tuple<int, IntProRowFunc, IntProRowFunc> IntProRowParam;
+
+class IntProRowTest
+    : public AverageTestBase,
+      public ::testing::WithParamInterface<IntProRowParam> {
+ public:
+  IntProRowTest()
+    : AverageTestBase(16, GET_PARAM(0)),
+      hbuf_asm_(NULL),
+      hbuf_c_(NULL) {
+    asm_func_ = GET_PARAM(1);
+    c_func_ = GET_PARAM(2);
+  }
+
+ protected:
+  virtual void SetUp() {
+    hbuf_asm_ = reinterpret_cast<int16_t*>(
+        vpx_memalign(kDataAlignment, sizeof(*hbuf_asm_) * 16));
+    hbuf_c_ = reinterpret_cast<int16_t*>(
+        vpx_memalign(kDataAlignment, sizeof(*hbuf_c_) * 16));
+  }
+
+  virtual void TearDown() {
+    vpx_free(hbuf_c_);
+    hbuf_c_ = NULL;
+    vpx_free(hbuf_asm_);
+    hbuf_asm_ = NULL;
+  }
+
+  void RunComparison() {
+    ASM_REGISTER_STATE_CHECK(c_func_(hbuf_c_, source_data_, 0, height_));
+    ASM_REGISTER_STATE_CHECK(asm_func_(hbuf_asm_, source_data_, 0, height_));
+    EXPECT_EQ(0, memcmp(hbuf_c_, hbuf_asm_, sizeof(*hbuf_c_) * 16))
+        << "Output mismatch";
+  }
+
+ private:
+  IntProRowFunc asm_func_;
+  IntProRowFunc c_func_;
+  int16_t *hbuf_asm_;
+  int16_t *hbuf_c_;
+};
+
+typedef int16_t (*IntProColFunc)(uint8_t const *ref, const int width);
+
+typedef std::tr1::tuple<int, IntProColFunc, IntProColFunc> IntProColParam;
+
+class IntProColTest
+    : public AverageTestBase,
+      public ::testing::WithParamInterface<IntProColParam> {
+ public:
+  IntProColTest() : AverageTestBase(GET_PARAM(0), 1), sum_asm_(0), sum_c_(0) {
+    asm_func_ = GET_PARAM(1);
+    c_func_ = GET_PARAM(2);
+  }
+
+ protected:
+  void RunComparison() {
+    ASM_REGISTER_STATE_CHECK(sum_c_ = c_func_(source_data_, width_));
+    ASM_REGISTER_STATE_CHECK(sum_asm_ = asm_func_(source_data_, width_));
+    EXPECT_EQ(sum_c_, sum_asm_) << "Output mismatch";
+  }
+
+ private:
+  IntProColFunc asm_func_;
+  IntProColFunc c_func_;
+  int16_t sum_asm_;
+  int16_t sum_c_;
+};
+
+typedef int (*SatdFunc)(const int16_t *coeffs, int length);
+typedef std::tr1::tuple<int, SatdFunc> SatdTestParam;
+
+class SatdTest
+    : public ::testing::Test,
+      public ::testing::WithParamInterface<SatdTestParam> {
+ protected:
+  virtual void SetUp() {
+    satd_size_ = GET_PARAM(0);
+    satd_func_ = GET_PARAM(1);
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+    src_ = reinterpret_cast<int16_t*>(
+        vpx_memalign(16, sizeof(*src_) * satd_size_));
+    ASSERT_TRUE(src_ != NULL);
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+    vpx_free(src_);
+  }
+
+  void FillConstant(const int16_t val) {
+    for (int i = 0; i < satd_size_; ++i) src_[i] = val;
+  }
+
+  void FillRandom() {
+    for (int i = 0; i < satd_size_; ++i) src_[i] = rnd_.Rand16();
+  }
+
+  void Check(const int expected) {
+    int total;
+    ASM_REGISTER_STATE_CHECK(total = satd_func_(src_, satd_size_));
+    EXPECT_EQ(expected, total);
+  }
+
+  int satd_size_;
+
+ private:
+  int16_t *src_;
+  SatdFunc satd_func_;
+  ACMRandom rnd_;
+};
+
+uint8_t* AverageTestBase::source_data_ = NULL;
+
+TEST_P(AverageTest, MinValue) {
+  FillConstant(0);
+  CheckAverages();
+}
+
+TEST_P(AverageTest, MaxValue) {
+  FillConstant(255);
+  CheckAverages();
+}
+
+TEST_P(AverageTest, Random) {
+  // The reference frame, but not the source frame, may be unaligned for
+  // certain types of searches.
+  for (int i = 0; i < 1000; i++) {
+    FillRandom();
+    CheckAverages();
+  }
+}
+
+TEST_P(IntProRowTest, MinValue) {
+  FillConstant(0);
+  RunComparison();
+}
+
+TEST_P(IntProRowTest, MaxValue) {
+  FillConstant(255);
+  RunComparison();
+}
+
+TEST_P(IntProRowTest, Random) {
+  FillRandom();
+  RunComparison();
+}
+
+TEST_P(IntProColTest, MinValue) {
+  FillConstant(0);
+  RunComparison();
+}
+
+TEST_P(IntProColTest, MaxValue) {
+  FillConstant(255);
+  RunComparison();
+}
+
+TEST_P(IntProColTest, Random) {
+  FillRandom();
+  RunComparison();
+}
+
+
+TEST_P(SatdTest, MinValue) {
+  const int kMin = -32640;
+  const int expected = -kMin * satd_size_;
+  FillConstant(kMin);
+  Check(expected);
+}
+
+TEST_P(SatdTest, MaxValue) {
+  const int kMax = 32640;
+  const int expected = kMax * satd_size_;
+  FillConstant(kMax);
+  Check(expected);
+}
+
+TEST_P(SatdTest, Random) {
+  int expected;
+  switch (satd_size_) {
+    case 16: expected = 205298; break;
+    case 64: expected = 1113950; break;
+    case 256: expected = 4268415; break;
+    case 1024: expected = 16954082; break;
+    default:
+      FAIL() << "Invalid satd size (" << satd_size_
+             << ") valid: 16/64/256/1024";
+  }
+  FillRandom();
+  Check(expected);
+}
+
+using std::tr1::make_tuple;
+
+INSTANTIATE_TEST_CASE_P(
+    C, AverageTest,
+    ::testing::Values(
+        make_tuple(16, 16, 1, 8, &vpx_avg_8x8_c),
+        make_tuple(16, 16, 1, 4, &vpx_avg_4x4_c)));
+
+INSTANTIATE_TEST_CASE_P(
+    C, SatdTest,
+    ::testing::Values(
+        make_tuple(16, &vpx_satd_c),
+        make_tuple(64, &vpx_satd_c),
+        make_tuple(256, &vpx_satd_c),
+        make_tuple(1024, &vpx_satd_c)));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(
+    SSE2, AverageTest,
+    ::testing::Values(
+        make_tuple(16, 16, 0, 8, &vpx_avg_8x8_sse2),
+        make_tuple(16, 16, 5, 8, &vpx_avg_8x8_sse2),
+        make_tuple(32, 32, 15, 8, &vpx_avg_8x8_sse2),
+        make_tuple(16, 16, 0, 4, &vpx_avg_4x4_sse2),
+        make_tuple(16, 16, 5, 4, &vpx_avg_4x4_sse2),
+        make_tuple(32, 32, 15, 4, &vpx_avg_4x4_sse2)));
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, IntProRowTest, ::testing::Values(
+        make_tuple(16, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
+        make_tuple(32, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c),
+        make_tuple(64, &vpx_int_pro_row_sse2, &vpx_int_pro_row_c)));
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, IntProColTest, ::testing::Values(
+        make_tuple(16, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
+        make_tuple(32, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c),
+        make_tuple(64, &vpx_int_pro_col_sse2, &vpx_int_pro_col_c)));
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, SatdTest,
+    ::testing::Values(
+        make_tuple(16, &vpx_satd_sse2),
+        make_tuple(64, &vpx_satd_sse2),
+        make_tuple(256, &vpx_satd_sse2),
+        make_tuple(1024, &vpx_satd_sse2)));
+#endif
+
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(
+    NEON, AverageTest,
+    ::testing::Values(
+        make_tuple(16, 16, 0, 8, &vpx_avg_8x8_neon),
+        make_tuple(16, 16, 5, 8, &vpx_avg_8x8_neon),
+        make_tuple(32, 32, 15, 8, &vpx_avg_8x8_neon),
+        make_tuple(16, 16, 0, 4, &vpx_avg_4x4_neon),
+        make_tuple(16, 16, 5, 4, &vpx_avg_4x4_neon),
+        make_tuple(32, 32, 15, 4, &vpx_avg_4x4_neon)));
+
+INSTANTIATE_TEST_CASE_P(
+    NEON, IntProRowTest, ::testing::Values(
+        make_tuple(16, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
+        make_tuple(32, &vpx_int_pro_row_neon, &vpx_int_pro_row_c),
+        make_tuple(64, &vpx_int_pro_row_neon, &vpx_int_pro_row_c)));
+
+INSTANTIATE_TEST_CASE_P(
+    NEON, IntProColTest, ::testing::Values(
+        make_tuple(16, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
+        make_tuple(32, &vpx_int_pro_col_neon, &vpx_int_pro_col_c),
+        make_tuple(64, &vpx_int_pro_col_neon, &vpx_int_pro_col_c)));
+
+INSTANTIATE_TEST_CASE_P(
+    NEON, SatdTest,
+    ::testing::Values(
+        make_tuple(16, &vpx_satd_neon),
+        make_tuple(64, &vpx_satd_neon),
+        make_tuple(256, &vpx_satd_neon),
+        make_tuple(1024, &vpx_satd_neon)));
+#endif
+
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(
+    MSA, AverageTest,
+    ::testing::Values(
+        make_tuple(16, 16, 0, 8, &vpx_avg_8x8_msa),
+        make_tuple(16, 16, 5, 8, &vpx_avg_8x8_msa),
+        make_tuple(32, 32, 15, 8, &vpx_avg_8x8_msa),
+        make_tuple(16, 16, 0, 4, &vpx_avg_4x4_msa),
+        make_tuple(16, 16, 5, 4, &vpx_avg_4x4_msa),
+        make_tuple(32, 32, 15, 4, &vpx_avg_4x4_msa)));
+#endif
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/blockiness_test.cc b/src/third_party/libvpx/test/blockiness_test.cc
new file mode 100644
index 0000000..0c60baa
--- /dev/null
+++ b/src/third_party/libvpx/test/blockiness_test.cc
@@ -0,0 +1,229 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP9_ENCODER
+#include "./vp9_rtcd.h"
+#endif
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+
+#include "vpx_mem/vpx_mem.h"
+
+
+extern "C"
+double vp9_get_blockiness(const unsigned char *img1, int img1_pitch,
+                          const unsigned char *img2, int img2_pitch,
+                          int width, int height);
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class BlockinessTestBase : public ::testing::Test {
+ public:
+  BlockinessTestBase(int width, int height) : width_(width), height_(height) {}
+
+  static void SetUpTestCase() {
+    source_data_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    reference_data_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+  }
+
+  static void TearDownTestCase() {
+    vpx_free(source_data_);
+    source_data_ = NULL;
+    vpx_free(reference_data_);
+    reference_data_ = NULL;
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  // Handle frames up to 640x480
+  static const int kDataAlignment = 16;
+  static const int kDataBufferSize = 640*480;
+
+  virtual void SetUp() {
+    source_stride_ = (width_ + 31) & ~31;
+    reference_stride_ = width_ * 2;
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+  void FillConstant(uint8_t *data, int stride, uint8_t fill_constant,
+                    int width, int height) {
+    for (int h = 0; h < height; ++h) {
+      for (int w = 0; w < width; ++w) {
+        data[h * stride + w] = fill_constant;
+      }
+    }
+  }
+
+  void FillConstant(uint8_t *data, int stride, uint8_t fill_constant) {
+    FillConstant(data, stride, fill_constant, width_, height_);
+  }
+
+  void FillRandom(uint8_t *data, int stride, int width, int height) {
+    for (int h = 0; h < height; ++h) {
+      for (int w = 0; w < width; ++w) {
+        data[h * stride + w] = rnd_.Rand8();
+      }
+    }
+  }
+
+  void FillRandom(uint8_t *data, int stride) {
+    FillRandom(data, stride, width_, height_);
+  }
+
+  void FillRandomBlocky(uint8_t *data, int stride) {
+    for (int h = 0; h < height_; h += 4) {
+      for (int w = 0; w < width_; w += 4) {
+        FillRandom(data + h * stride + w, stride, 4, 4);
+      }
+    }
+  }
+
+  void FillCheckerboard(uint8_t *data, int stride) {
+    for (int h = 0; h < height_; h += 4) {
+      for (int w = 0; w < width_; w += 4) {
+        if (((h/4) ^ (w/4)) & 1)
+          FillConstant(data + h * stride + w, stride, 255, 4, 4);
+        else
+          FillConstant(data + h * stride + w, stride, 0, 4, 4);
+      }
+    }
+  }
+
+  void Blur(uint8_t *data, int stride, int taps) {
+    int sum = 0;
+    int half_taps = taps / 2;
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < taps; ++w) {
+        sum += data[w + h * stride];
+      }
+      for (int w = taps; w < width_; ++w) {
+        sum += data[w + h * stride] - data[w - taps + h * stride];
+        data[w - half_taps + h * stride] = (sum + half_taps) / taps;
+      }
+    }
+    for (int w = 0; w < width_; ++w) {
+      for (int h = 0; h < taps; ++h) {
+        sum += data[h + w * stride];
+      }
+      for (int h = taps; h < height_; ++h) {
+        sum += data[w + h * stride] - data[(h - taps) * stride + w];
+        data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
+      }
+    }
+  }
+  int width_, height_;
+  static uint8_t* source_data_;
+  int source_stride_;
+  static uint8_t* reference_data_;
+  int reference_stride_;
+
+  ACMRandom rnd_;
+};
+
+#if CONFIG_VP9_ENCODER
+typedef std::tr1::tuple<int, int> BlockinessParam;
+class BlockinessVP9Test
+    : public BlockinessTestBase,
+      public ::testing::WithParamInterface<BlockinessParam> {
+ public:
+  BlockinessVP9Test() : BlockinessTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+  int CheckBlockiness() {
+    return vp9_get_blockiness(source_data_, source_stride_,
+                              reference_data_, reference_stride_,
+                              width_, height_);
+  }
+};
+#endif  // CONFIG_VP9_ENCODER
+
+uint8_t* BlockinessTestBase::source_data_ = NULL;
+uint8_t* BlockinessTestBase::reference_data_ = NULL;
+
+#if CONFIG_VP9_ENCODER
+TEST_P(BlockinessVP9Test, SourceBlockierThanReference) {
+  // Source is blockier than reference.
+  FillRandomBlocky(source_data_, source_stride_);
+  FillConstant(reference_data_, reference_stride_, 128);
+  int super_blocky = CheckBlockiness();
+
+  EXPECT_EQ(0, super_blocky) << "Blocky source should produce 0 blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, ReferenceBlockierThanSource) {
+  // Source is blockier than reference.
+  FillConstant(source_data_, source_stride_, 128);
+  FillRandomBlocky(reference_data_, reference_stride_);
+  int super_blocky = CheckBlockiness();
+
+  EXPECT_GT(super_blocky, 0.0)
+      << "Blocky reference should score high for blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, BlurringDecreasesBlockiness) {
+  // Source is blockier than reference.
+  FillConstant(source_data_, source_stride_, 128);
+  FillRandomBlocky(reference_data_, reference_stride_);
+  int super_blocky = CheckBlockiness();
+
+  Blur(reference_data_, reference_stride_, 4);
+  int less_blocky = CheckBlockiness();
+
+  EXPECT_GT(super_blocky, less_blocky)
+      << "A straight blur should decrease blockiness.";
+}
+
+TEST_P(BlockinessVP9Test, WorstCaseBlockiness) {
+  // Source is blockier than reference.
+  FillConstant(source_data_, source_stride_, 128);
+  FillCheckerboard(reference_data_, reference_stride_);
+
+  int super_blocky = CheckBlockiness();
+
+  Blur(reference_data_, reference_stride_, 4);
+  int less_blocky = CheckBlockiness();
+
+  EXPECT_GT(super_blocky, less_blocky)
+      << "A straight blur should decrease blockiness.";
+}
+#endif  // CONFIG_VP9_ENCODER
+
+
+using std::tr1::make_tuple;
+
+//------------------------------------------------------------------------------
+// C functions
+
+#if CONFIG_VP9_ENCODER
+const BlockinessParam c_vp9_tests[] = {
+  make_tuple(320, 240),
+  make_tuple(318, 242),
+  make_tuple(318, 238),
+};
+INSTANTIATE_TEST_CASE_P(C, BlockinessVP9Test, ::testing::ValuesIn(c_vp9_tests));
+#endif
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/borders_test.cc b/src/third_party/libvpx/test/borders_test.cc
new file mode 100644
index 0000000..ff3812c
--- /dev/null
+++ b/src/third_party/libvpx/test/borders_test.cc
@@ -0,0 +1,86 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class BordersTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  BordersTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~BordersTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, 1);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+      encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+      encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+    }
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+    }
+  }
+};
+
+TEST_P(BordersTest, TestEncodeHighBitrate) {
+  // Validate that this non multiple of 64 wide clip encodes and decodes
+  // without a mismatch when passing in a very low max q.  This pushes
+  // the encoder to producing lots of big partitions which will likely
+  // extend into the border and test the border condition.
+  cfg_.g_lag_in_frames = 25;
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 2000;
+  cfg_.rc_max_quantizer = 10;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+TEST_P(BordersTest, TestLowBitrate) {
+  // Validate that this clip encodes and decodes without a mismatch
+  // when passing in a very high min q.  This pushes the encoder to producing
+  // lots of small partitions which might will test the other condition.
+
+  cfg_.g_lag_in_frames = 25;
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 200;
+  cfg_.rc_min_quantizer = 40;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values(
+    ::libvpx_test::kTwoPassGood));
+
+VP10_INSTANTIATE_TEST_CASE(BordersTest, ::testing::Values(
+    ::libvpx_test::kTwoPassGood));
+}  // namespace
diff --git a/src/third_party/libvpx/test/byte_alignment_test.cc b/src/third_party/libvpx/test/byte_alignment_test.cc
new file mode 100644
index 0000000..3a808b0
--- /dev/null
+++ b/src/third_party/libvpx/test/byte_alignment_test.cc
@@ -0,0 +1,189 @@
+/*
+ *  Copyright (c) 2014 The WebM 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>
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+
+namespace {
+
+#if CONFIG_WEBM_IO
+
+const int kLegacyByteAlignment = 0;
+const int kLegacyYPlaneByteAlignment = 32;
+const int kNumPlanesToCheck = 3;
+const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
+const char kVP9Md5File[] = "vp90-2-02-size-lf-1920x1080.webm.md5";
+
+struct ByteAlignmentTestParam {
+  int byte_alignment;
+  vpx_codec_err_t expected_value;
+  bool decode_remaining;
+};
+
+const ByteAlignmentTestParam kBaTestParams[] = {
+  {kLegacyByteAlignment, VPX_CODEC_OK, true},
+  {32, VPX_CODEC_OK, true},
+  {64, VPX_CODEC_OK, true},
+  {128, VPX_CODEC_OK, true},
+  {256, VPX_CODEC_OK, true},
+  {512, VPX_CODEC_OK, true},
+  {1024, VPX_CODEC_OK, true},
+  {1, VPX_CODEC_INVALID_PARAM, false},
+  {-2, VPX_CODEC_INVALID_PARAM, false},
+  {4, VPX_CODEC_INVALID_PARAM, false},
+  {16, VPX_CODEC_INVALID_PARAM, false},
+  {255, VPX_CODEC_INVALID_PARAM, false},
+  {2048, VPX_CODEC_INVALID_PARAM, false},
+};
+
+// Class for testing byte alignment of reference buffers.
+class ByteAlignmentTest
+    : public ::testing::TestWithParam<ByteAlignmentTestParam> {
+ protected:
+  ByteAlignmentTest()
+      : video_(NULL),
+        decoder_(NULL),
+        md5_file_(NULL) {}
+
+  virtual void SetUp() {
+    video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
+    ASSERT_TRUE(video_ != NULL);
+    video_->Init();
+    video_->Begin();
+
+    const vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+    decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+    ASSERT_TRUE(decoder_ != NULL);
+
+    OpenMd5File(kVP9Md5File);
+  }
+
+  virtual void TearDown() {
+    if (md5_file_ != NULL)
+      fclose(md5_file_);
+
+    delete decoder_;
+    delete video_;
+  }
+
+  void SetByteAlignment(int byte_alignment, vpx_codec_err_t expected_value) {
+    decoder_->Control(VP9_SET_BYTE_ALIGNMENT, byte_alignment, expected_value);
+  }
+
+  vpx_codec_err_t DecodeOneFrame(int byte_alignment_to_check) {
+    const vpx_codec_err_t res =
+        decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+    CheckDecodedFrames(byte_alignment_to_check);
+    if (res == VPX_CODEC_OK)
+      video_->Next();
+    return res;
+  }
+
+  vpx_codec_err_t DecodeRemainingFrames(int byte_alignment_to_check) {
+    for (; video_->cxdata() != NULL; video_->Next()) {
+      const vpx_codec_err_t res =
+          decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+      if (res != VPX_CODEC_OK)
+        return res;
+      CheckDecodedFrames(byte_alignment_to_check);
+    }
+    return VPX_CODEC_OK;
+  }
+
+ private:
+  // Check if |data| is aligned to |byte_alignment_to_check|.
+  // |byte_alignment_to_check| must be a power of 2.
+  void CheckByteAlignment(const uint8_t *data, int byte_alignment_to_check) {
+    ASSERT_EQ(0u, reinterpret_cast<size_t>(data) % byte_alignment_to_check);
+  }
+
+  // Iterate through the planes of the decoded frames and check for
+  // alignment based off |byte_alignment_to_check|.
+  void CheckDecodedFrames(int byte_alignment_to_check) {
+    libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+    const vpx_image_t *img;
+
+    // Get decompressed data
+    while ((img = dec_iter.Next()) != NULL) {
+      if (byte_alignment_to_check == kLegacyByteAlignment) {
+        CheckByteAlignment(img->planes[0], kLegacyYPlaneByteAlignment);
+      } else {
+        for (int i = 0; i < kNumPlanesToCheck; ++i) {
+          CheckByteAlignment(img->planes[i], byte_alignment_to_check);
+        }
+      }
+      CheckMd5(*img);
+    }
+  }
+
+  // TODO(fgalligan): Move the MD5 testing code into another class.
+  void OpenMd5File(const std::string &md5_file_name_) {
+    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+    ASSERT_TRUE(md5_file_ != NULL) << "MD5 file open failed. Filename: "
+        << md5_file_name_;
+  }
+
+  void CheckMd5(const vpx_image_t &img) {
+    ASSERT_TRUE(md5_file_ != NULL);
+    char expected_md5[33];
+    char junk[128];
+
+    // Read correct md5 checksums.
+    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
+    ASSERT_NE(EOF, res) << "Read md5 data failed";
+    expected_md5[32] = '\0';
+
+    ::libvpx_test::MD5 md5_res;
+    md5_res.Add(&img);
+    const char *const actual_md5 = md5_res.Get();
+
+    // Check md5 match.
+    ASSERT_STREQ(expected_md5, actual_md5) << "MD5 checksums don't match";
+  }
+
+  libvpx_test::WebMVideoSource *video_;
+  libvpx_test::VP9Decoder *decoder_;
+  FILE *md5_file_;
+};
+
+TEST_F(ByteAlignmentTest, SwitchByteAlignment) {
+  const int num_elements = 14;
+  const int byte_alignments[] = { 0, 32, 64, 128, 256, 512, 1024,
+                                  0, 1024, 32, 512, 64, 256, 128 };
+
+  for (int i = 0; i < num_elements; ++i) {
+    SetByteAlignment(byte_alignments[i], VPX_CODEC_OK);
+    ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame(byte_alignments[i]));
+  }
+  SetByteAlignment(byte_alignments[0], VPX_CODEC_OK);
+  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(byte_alignments[0]));
+}
+
+TEST_P(ByteAlignmentTest, TestAlignment) {
+  const ByteAlignmentTestParam t = GetParam();
+  SetByteAlignment(t.byte_alignment, t.expected_value);
+  if (t.decode_remaining)
+    ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames(t.byte_alignment));
+}
+
+INSTANTIATE_TEST_CASE_P(Alignments, ByteAlignmentTest,
+                        ::testing::ValuesIn(kBaTestParams));
+
+#endif  // CONFIG_WEBM_IO
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/clear_system_state.h b/src/third_party/libvpx/test/clear_system_state.h
new file mode 100644
index 0000000..5e76797
--- /dev/null
+++ b/src/third_party/libvpx/test/clear_system_state.h
@@ -0,0 +1,29 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 TEST_CLEAR_SYSTEM_STATE_H_
+#define TEST_CLEAR_SYSTEM_STATE_H_
+
+#include "./vpx_config.h"
+#if ARCH_X86 || ARCH_X86_64
+# include "vpx_ports/x86.h"
+#endif
+
+namespace libvpx_test {
+
+// Reset system to a known state. This function should be used for all non-API
+// test cases.
+inline void ClearSystemState() {
+#if ARCH_X86 || ARCH_X86_64
+  vpx_reset_mmx_state();
+#endif
+}
+
+}  // namespace libvpx_test
+#endif  // TEST_CLEAR_SYSTEM_STATE_H_
diff --git a/src/third_party/libvpx/test/codec_factory.h b/src/third_party/libvpx/test/codec_factory.h
new file mode 100644
index 0000000..09c9cf9
--- /dev/null
+++ b/src/third_party/libvpx/test/codec_factory.h
@@ -0,0 +1,348 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 TEST_CODEC_FACTORY_H_
+#define TEST_CODEC_FACTORY_H_
+
+#include "./vpx_config.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx/vpx_encoder.h"
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+#if CONFIG_VP8_DECODER || CONFIG_VP9_DECODER || CONFIG_VP10_DECODER
+#include "vpx/vp8dx.h"
+#endif
+
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+namespace libvpx_test {
+
+const int kCodecFactoryParam = 0;
+
+class CodecFactory {
+ public:
+  CodecFactory() {}
+
+  virtual ~CodecFactory() {}
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 unsigned long deadline) const = 0;
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 const vpx_codec_flags_t flags,
+                                 unsigned long deadline)  // NOLINT(runtime/int)
+                                 const = 0;
+
+  virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
+                                 unsigned long deadline,
+                                 const unsigned long init_flags,
+                                 TwopassStatsStore *stats) const = 0;
+
+  virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+                                               int usage) const = 0;
+};
+
+/* Provide CodecTestWith<n>Params classes for a variable number of parameters
+ * to avoid having to include a pointer to the CodecFactory in every test
+ * definition.
+ */
+template<class T1>
+class CodecTestWithParam : public ::testing::TestWithParam<
+    std::tr1::tuple< const libvpx_test::CodecFactory*, T1 > > {
+};
+
+template<class T1, class T2>
+class CodecTestWith2Params : public ::testing::TestWithParam<
+    std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2 > > {
+};
+
+template<class T1, class T2, class T3>
+class CodecTestWith3Params : public ::testing::TestWithParam<
+    std::tr1::tuple< const libvpx_test::CodecFactory*, T1, T2, T3 > > {
+};
+
+/*
+ * VP8 Codec Definitions
+ */
+#if CONFIG_VP8
+class VP8Decoder : public Decoder {
+ public:
+  VP8Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
+      : Decoder(cfg, deadline) {}
+
+  VP8Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+             unsigned long deadline)  // NOLINT
+      : Decoder(cfg, flag, deadline) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP8_DECODER
+    return &vpx_codec_vp8_dx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP8Encoder : public Encoder {
+ public:
+  VP8Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+             const unsigned long init_flags, TwopassStatsStore *stats)
+      : Encoder(cfg, deadline, init_flags, stats) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP8_ENCODER
+    return &vpx_codec_vp8_cx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP8CodecFactory : public CodecFactory {
+ public:
+  VP8CodecFactory() : CodecFactory() {}
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 unsigned long deadline) const {
+    return CreateDecoder(cfg, 0, deadline);
+  }
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 const vpx_codec_flags_t flags,
+                                 unsigned long deadline) const {  // NOLINT
+#if CONFIG_VP8_DECODER
+    return new VP8Decoder(cfg, flags, deadline);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
+                                 unsigned long deadline,
+                                 const unsigned long init_flags,
+                                 TwopassStatsStore *stats) const {
+#if CONFIG_VP8_ENCODER
+    return new VP8Encoder(cfg, deadline, init_flags, stats);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+                                               int usage) const {
+#if CONFIG_VP8_ENCODER
+    return vpx_codec_enc_config_default(&vpx_codec_vp8_cx_algo, cfg, usage);
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+  }
+};
+
+const libvpx_test::VP8CodecFactory kVP8;
+
+#define VP8_INSTANTIATE_TEST_CASE(test, ...)\
+  INSTANTIATE_TEST_CASE_P(VP8, test, \
+      ::testing::Combine( \
+          ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
+              &libvpx_test::kVP8)), \
+          __VA_ARGS__))
+#else
+#define VP8_INSTANTIATE_TEST_CASE(test, ...)
+#endif  // CONFIG_VP8
+
+
+/*
+ * VP9 Codec Definitions
+ */
+#if CONFIG_VP9
+class VP9Decoder : public Decoder {
+ public:
+  VP9Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
+      : Decoder(cfg, deadline) {}
+
+  VP9Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+             unsigned long deadline)  // NOLINT
+      : Decoder(cfg, flag, deadline) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP9_DECODER
+    return &vpx_codec_vp9_dx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP9Encoder : public Encoder {
+ public:
+  VP9Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+             const unsigned long init_flags, TwopassStatsStore *stats)
+      : Encoder(cfg, deadline, init_flags, stats) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP9_ENCODER
+    return &vpx_codec_vp9_cx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP9CodecFactory : public CodecFactory {
+ public:
+  VP9CodecFactory() : CodecFactory() {}
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 unsigned long deadline) const {
+    return CreateDecoder(cfg, 0, deadline);
+  }
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 const vpx_codec_flags_t flags,
+                                 unsigned long deadline) const {  // NOLINT
+#if CONFIG_VP9_DECODER
+    return new VP9Decoder(cfg, flags, deadline);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
+                                 unsigned long deadline,
+                                 const unsigned long init_flags,
+                                 TwopassStatsStore *stats) const {
+#if CONFIG_VP9_ENCODER
+    return new VP9Encoder(cfg, deadline, init_flags, stats);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+                                               int usage) const {
+#if CONFIG_VP9_ENCODER
+    return vpx_codec_enc_config_default(&vpx_codec_vp9_cx_algo, cfg, usage);
+#elif CONFIG_VP10_ENCODER
+    return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage);
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+  }
+};
+
+const libvpx_test::VP9CodecFactory kVP9;
+
+#define VP9_INSTANTIATE_TEST_CASE(test, ...)\
+  INSTANTIATE_TEST_CASE_P(VP9, test, \
+      ::testing::Combine( \
+          ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
+               &libvpx_test::kVP9)), \
+          __VA_ARGS__))
+#else
+#define VP9_INSTANTIATE_TEST_CASE(test, ...)
+#endif  // CONFIG_VP9
+
+/*
+ * VP10 Codec Definitions
+ */
+#if CONFIG_VP10
+class VP10Decoder : public Decoder {
+ public:
+  VP10Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
+      : Decoder(cfg, deadline) {}
+
+  VP10Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+              unsigned long deadline)  // NOLINT
+      : Decoder(cfg, flag, deadline) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP10_DECODER
+    return &vpx_codec_vp10_dx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP10Encoder : public Encoder {
+ public:
+  VP10Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+              const unsigned long init_flags, TwopassStatsStore *stats)
+      : Encoder(cfg, deadline, init_flags, stats) {}
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const {
+#if CONFIG_VP10_ENCODER
+    return &vpx_codec_vp10_cx_algo;
+#else
+    return NULL;
+#endif
+  }
+};
+
+class VP10CodecFactory : public CodecFactory {
+ public:
+  VP10CodecFactory() : CodecFactory() {}
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 unsigned long deadline) const {
+    return CreateDecoder(cfg, 0, deadline);
+  }
+
+  virtual Decoder* CreateDecoder(vpx_codec_dec_cfg_t cfg,
+                                 const vpx_codec_flags_t flags,
+                                 unsigned long deadline) const {  // NOLINT
+#if CONFIG_VP10_DECODER
+    return new VP10Decoder(cfg, flags, deadline);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual Encoder* CreateEncoder(vpx_codec_enc_cfg_t cfg,
+                                 unsigned long deadline,
+                                 const unsigned long init_flags,
+                                 TwopassStatsStore *stats) const {
+#if CONFIG_VP10_ENCODER
+    return new VP10Encoder(cfg, deadline, init_flags, stats);
+#else
+    return NULL;
+#endif
+  }
+
+  virtual vpx_codec_err_t DefaultEncoderConfig(vpx_codec_enc_cfg_t *cfg,
+                                               int usage) const {
+#if CONFIG_VP10_ENCODER
+    return vpx_codec_enc_config_default(&vpx_codec_vp10_cx_algo, cfg, usage);
+#else
+    return VPX_CODEC_INCAPABLE;
+#endif
+  }
+};
+
+const libvpx_test::VP10CodecFactory kVP10;
+
+#define VP10_INSTANTIATE_TEST_CASE(test, ...)\
+  INSTANTIATE_TEST_CASE_P(VP10, test, \
+      ::testing::Combine( \
+          ::testing::Values(static_cast<const libvpx_test::CodecFactory*>( \
+               &libvpx_test::kVP10)), \
+          __VA_ARGS__))
+#else
+#define VP10_INSTANTIATE_TEST_CASE(test, ...)
+#endif  // CONFIG_VP10
+
+}  // namespace libvpx_test
+#endif  // TEST_CODEC_FACTORY_H_
diff --git a/src/third_party/libvpx/test/config_test.cc b/src/third_party/libvpx/test/config_test.cc
new file mode 100644
index 0000000..0493110
--- /dev/null
+++ b/src/third_party/libvpx/test/config_test.cc
@@ -0,0 +1,60 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/video_source.h"
+
+namespace {
+
+class ConfigTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  ConfigTest() : EncoderTest(GET_PARAM(0)),
+                 frame_count_in_(0), frame_count_out_(0), frame_count_max_(0) {}
+  virtual ~ConfigTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    frame_count_in_ = 0;
+    frame_count_out_ = 0;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource* /*video*/) {
+    ++frame_count_in_;
+    abort_ |= (frame_count_in_ >= frame_count_max_);
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {
+    ++frame_count_out_;
+  }
+
+  unsigned int frame_count_in_;
+  unsigned int frame_count_out_;
+  unsigned int frame_count_max_;
+};
+
+TEST_P(ConfigTest, LagIsDisabled) {
+  frame_count_max_ = 2;
+  cfg_.g_lag_in_frames = 15;
+
+  libvpx_test::DummyVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  EXPECT_EQ(frame_count_in_, frame_count_out_);
+}
+
+VP8_INSTANTIATE_TEST_CASE(ConfigTest, ONE_PASS_TEST_MODES);
+}  // namespace
diff --git a/src/third_party/libvpx/test/consistency_test.cc b/src/third_party/libvpx/test/consistency_test.cc
new file mode 100644
index 0000000..9c2fd55
--- /dev/null
+++ b/src/third_party/libvpx/test/consistency_test.cc
@@ -0,0 +1,224 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP9_ENCODER
+#include "./vp9_rtcd.h"
+#endif
+
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx_dsp/ssim.h"
+#include "vpx_mem/vpx_mem.h"
+
+extern "C"
+double vpx_get_ssim_metrics(uint8_t *img1, int img1_pitch,
+                            uint8_t *img2, int img2_pitch,
+                            int width, int height,
+                            Ssimv *sv2, Metrics *m,
+                            int do_inconsistency);
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class ConsistencyTestBase : public ::testing::Test {
+ public:
+  ConsistencyTestBase(int width, int height) : width_(width), height_(height) {}
+
+  static void SetUpTestCase() {
+    source_data_[0] = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    reference_data_[0] = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    source_data_[1] = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    reference_data_[1] = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    ssim_array_ = new Ssimv[kDataBufferSize / 16];
+  }
+
+  static void ClearSsim() {
+    memset(ssim_array_, 0, kDataBufferSize / 16);
+  }
+  static void TearDownTestCase() {
+    vpx_free(source_data_[0]);
+    source_data_[0] = NULL;
+    vpx_free(reference_data_[0]);
+    reference_data_[0] = NULL;
+    vpx_free(source_data_[1]);
+    source_data_[1] = NULL;
+    vpx_free(reference_data_[1]);
+    reference_data_[1] = NULL;
+
+    delete[] ssim_array_;
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  // Handle frames up to 640x480
+  static const int kDataAlignment = 16;
+  static const int kDataBufferSize = 640*480;
+
+  virtual void SetUp() {
+    source_stride_ = (width_ + 31) & ~31;
+    reference_stride_ = width_ * 2;
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+  void FillRandom(uint8_t *data, int stride, int width, int height) {
+    for (int h = 0; h < height; ++h) {
+      for (int w = 0; w < width; ++w) {
+        data[h * stride + w] = rnd_.Rand8();
+      }
+    }
+  }
+
+  void FillRandom(uint8_t *data, int stride) {
+    FillRandom(data, stride, width_, height_);
+  }
+
+  void Copy(uint8_t *reference, uint8_t *source) {
+    memcpy(reference, source, kDataBufferSize);
+  }
+
+  void Blur(uint8_t *data, int stride, int taps) {
+    int sum = 0;
+    int half_taps = taps / 2;
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < taps; ++w) {
+        sum += data[w + h * stride];
+      }
+      for (int w = taps; w < width_; ++w) {
+        sum += data[w + h * stride] - data[w - taps + h * stride];
+        data[w - half_taps + h * stride] = (sum + half_taps) / taps;
+      }
+    }
+    for (int w = 0; w < width_; ++w) {
+      for (int h = 0; h < taps; ++h) {
+        sum += data[h + w * stride];
+      }
+      for (int h = taps; h < height_; ++h) {
+        sum += data[w + h * stride] - data[(h - taps) * stride + w];
+        data[(h - half_taps) * stride + w] = (sum + half_taps) / taps;
+      }
+    }
+  }
+  int width_, height_;
+  static uint8_t* source_data_[2];
+  int source_stride_;
+  static uint8_t* reference_data_[2];
+  int reference_stride_;
+  static Ssimv *ssim_array_;
+  Metrics metrics_;
+
+  ACMRandom rnd_;
+};
+
+#if CONFIG_VP9_ENCODER
+typedef std::tr1::tuple<int, int> ConsistencyParam;
+class ConsistencyVP9Test
+    : public ConsistencyTestBase,
+      public ::testing::WithParamInterface<ConsistencyParam> {
+ public:
+  ConsistencyVP9Test() : ConsistencyTestBase(GET_PARAM(0), GET_PARAM(1)) {}
+
+ protected:
+  double CheckConsistency(int frame) {
+    EXPECT_LT(frame, 2)<< "Frame to check has to be less than 2.";
+    return
+        vpx_get_ssim_metrics(source_data_[frame], source_stride_,
+                             reference_data_[frame], reference_stride_,
+                             width_, height_, ssim_array_, &metrics_, 1);
+  }
+};
+#endif  // CONFIG_VP9_ENCODER
+
+uint8_t* ConsistencyTestBase::source_data_[2] = {NULL, NULL};
+uint8_t* ConsistencyTestBase::reference_data_[2] = {NULL, NULL};
+Ssimv* ConsistencyTestBase::ssim_array_ = NULL;
+
+#if CONFIG_VP9_ENCODER
+TEST_P(ConsistencyVP9Test, ConsistencyIsZero) {
+  FillRandom(source_data_[0], source_stride_);
+  Copy(source_data_[1], source_data_[0]);
+  Copy(reference_data_[0], source_data_[0]);
+  Blur(reference_data_[0], reference_stride_, 3);
+  Copy(reference_data_[1], source_data_[0]);
+  Blur(reference_data_[1], reference_stride_, 3);
+
+  double inconsistency = CheckConsistency(1);
+  inconsistency = CheckConsistency(0);
+  EXPECT_EQ(inconsistency, 0.0)
+      << "Should have 0 inconsistency if they are exactly the same.";
+
+  // If sources are not consistent reference frames inconsistency should
+  // be less than if the source is consistent.
+  FillRandom(source_data_[0], source_stride_);
+  FillRandom(source_data_[1], source_stride_);
+  FillRandom(reference_data_[0], reference_stride_);
+  FillRandom(reference_data_[1], reference_stride_);
+  CheckConsistency(0);
+  inconsistency = CheckConsistency(1);
+
+  Copy(source_data_[1], source_data_[0]);
+  CheckConsistency(0);
+  double inconsistency2 = CheckConsistency(1);
+  EXPECT_LT(inconsistency, inconsistency2)
+      << "Should have less inconsistency if source itself is inconsistent.";
+
+  // Less of a blur should be less inconsistent than more blur coming off a
+  // a frame with no blur.
+  ClearSsim();
+  FillRandom(source_data_[0], source_stride_);
+  Copy(source_data_[1], source_data_[0]);
+  Copy(reference_data_[0], source_data_[0]);
+  Copy(reference_data_[1], source_data_[0]);
+  Blur(reference_data_[1], reference_stride_, 4);
+  CheckConsistency(0);
+  inconsistency = CheckConsistency(1);
+  ClearSsim();
+  Copy(reference_data_[1], source_data_[0]);
+  Blur(reference_data_[1], reference_stride_, 8);
+  CheckConsistency(0);
+  inconsistency2 = CheckConsistency(1);
+
+  EXPECT_LT(inconsistency, inconsistency2)
+      << "Stronger Blur should produce more inconsistency.";
+}
+#endif  // CONFIG_VP9_ENCODER
+
+
+using std::tr1::make_tuple;
+
+//------------------------------------------------------------------------------
+// C functions
+
+#if CONFIG_VP9_ENCODER
+const ConsistencyParam c_vp9_tests[] = {
+  make_tuple(320, 240),
+  make_tuple(318, 242),
+  make_tuple(318, 238),
+};
+INSTANTIATE_TEST_CASE_P(C, ConsistencyVP9Test,
+                        ::testing::ValuesIn(c_vp9_tests));
+#endif
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/convolve_test.cc b/src/third_party/libvpx/test/convolve_test.cc
new file mode 100644
index 0000000..73b0edb
--- /dev/null
+++ b/src/third_party/libvpx/test/convolve_test.cc
@@ -0,0 +1,1238 @@
+/*
+ *  Copyright (c) 2010 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_common.h"
+#include "vp9/common/vp9_filter.h"
+#include "vpx_dsp/vpx_dsp_common.h"
+#include "vpx_dsp/vpx_filter.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+
+namespace {
+
+static const unsigned int kMaxDimension = 64;
+
+typedef void (*ConvolveFunc)(const uint8_t *src, ptrdiff_t src_stride,
+                             uint8_t *dst, ptrdiff_t dst_stride,
+                             const int16_t *filter_x, int filter_x_stride,
+                             const int16_t *filter_y, int filter_y_stride,
+                             int w, int h);
+
+struct ConvolveFunctions {
+  ConvolveFunctions(ConvolveFunc copy, ConvolveFunc avg,
+                    ConvolveFunc h8, ConvolveFunc h8_avg,
+                    ConvolveFunc v8, ConvolveFunc v8_avg,
+                    ConvolveFunc hv8, ConvolveFunc hv8_avg,
+                    ConvolveFunc sh8, ConvolveFunc sh8_avg,
+                    ConvolveFunc sv8, ConvolveFunc sv8_avg,
+                    ConvolveFunc shv8, ConvolveFunc shv8_avg,
+                    int bd)
+      : copy_(copy), avg_(avg), h8_(h8), v8_(v8), hv8_(hv8), h8_avg_(h8_avg),
+        v8_avg_(v8_avg), hv8_avg_(hv8_avg), sh8_(sh8), sv8_(sv8), shv8_(shv8),
+        sh8_avg_(sh8_avg), sv8_avg_(sv8_avg), shv8_avg_(shv8_avg),
+        use_highbd_(bd) {}
+
+  ConvolveFunc copy_;
+  ConvolveFunc avg_;
+  ConvolveFunc h8_;
+  ConvolveFunc v8_;
+  ConvolveFunc hv8_;
+  ConvolveFunc h8_avg_;
+  ConvolveFunc v8_avg_;
+  ConvolveFunc hv8_avg_;
+  ConvolveFunc sh8_;        // scaled horiz
+  ConvolveFunc sv8_;        // scaled vert
+  ConvolveFunc shv8_;       // scaled horiz/vert
+  ConvolveFunc sh8_avg_;    // scaled avg horiz
+  ConvolveFunc sv8_avg_;    // scaled avg vert
+  ConvolveFunc shv8_avg_;   // scaled avg horiz/vert
+  int use_highbd_;  // 0 if high bitdepth not used, else the actual bit depth.
+};
+
+typedef std::tr1::tuple<int, int, const ConvolveFunctions *> ConvolveParam;
+
+#define ALL_SIZES(convolve_fn) \
+    make_tuple(4, 4, &convolve_fn),     \
+    make_tuple(8, 4, &convolve_fn),     \
+    make_tuple(4, 8, &convolve_fn),     \
+    make_tuple(8, 8, &convolve_fn),     \
+    make_tuple(16, 8, &convolve_fn),    \
+    make_tuple(8, 16, &convolve_fn),    \
+    make_tuple(16, 16, &convolve_fn),   \
+    make_tuple(32, 16, &convolve_fn),   \
+    make_tuple(16, 32, &convolve_fn),   \
+    make_tuple(32, 32, &convolve_fn),   \
+    make_tuple(64, 32, &convolve_fn),   \
+    make_tuple(32, 64, &convolve_fn),   \
+    make_tuple(64, 64, &convolve_fn)
+
+// Reference 8-tap subpixel filter, slightly modified to fit into this test.
+#define VP9_FILTER_WEIGHT 128
+#define VP9_FILTER_SHIFT 7
+uint8_t clip_pixel(int x) {
+  return x < 0 ? 0 :
+         x > 255 ? 255 :
+         x;
+}
+
+void filter_block2d_8_c(const uint8_t *src_ptr,
+                        const unsigned int src_stride,
+                        const int16_t *HFilter,
+                        const int16_t *VFilter,
+                        uint8_t *dst_ptr,
+                        unsigned int dst_stride,
+                        unsigned int output_width,
+                        unsigned int output_height) {
+  // Between passes, we use an intermediate buffer whose height is extended to
+  // have enough horizontally filtered values as input for the vertical pass.
+  // This buffer is allocated to be big enough for the largest block type we
+  // support.
+  const int kInterp_Extend = 4;
+  const unsigned int intermediate_height =
+      (kInterp_Extend - 1) + output_height + kInterp_Extend;
+  unsigned int i, j;
+
+  // Size of intermediate_buffer is max_intermediate_height * filter_max_width,
+  // where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height
+  //                                 + kInterp_Extend
+  //                               = 3 + 16 + 4
+  //                               = 23
+  // and filter_max_width          = 16
+  //
+  uint8_t intermediate_buffer[71 * kMaxDimension];
+  const int intermediate_next_stride =
+      1 - static_cast<int>(intermediate_height * output_width);
+
+  // Horizontal pass (src -> transposed intermediate).
+  uint8_t *output_ptr = intermediate_buffer;
+  const int src_next_row_stride = src_stride - output_width;
+  src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1);
+  for (i = 0; i < intermediate_height; ++i) {
+    for (j = 0; j < output_width; ++j) {
+      // Apply filter...
+      const int temp = (src_ptr[0] * HFilter[0]) +
+          (src_ptr[1] * HFilter[1]) +
+          (src_ptr[2] * HFilter[2]) +
+          (src_ptr[3] * HFilter[3]) +
+          (src_ptr[4] * HFilter[4]) +
+          (src_ptr[5] * HFilter[5]) +
+          (src_ptr[6] * HFilter[6]) +
+          (src_ptr[7] * HFilter[7]) +
+          (VP9_FILTER_WEIGHT >> 1);  // Rounding
+
+      // Normalize back to 0-255...
+      *output_ptr = clip_pixel(temp >> VP9_FILTER_SHIFT);
+      ++src_ptr;
+      output_ptr += intermediate_height;
+    }
+    src_ptr += src_next_row_stride;
+    output_ptr += intermediate_next_stride;
+  }
+
+  // Vertical pass (transposed intermediate -> dst).
+  src_ptr = intermediate_buffer;
+  const int dst_next_row_stride = dst_stride - output_width;
+  for (i = 0; i < output_height; ++i) {
+    for (j = 0; j < output_width; ++j) {
+      // Apply filter...
+      const int temp = (src_ptr[0] * VFilter[0]) +
+          (src_ptr[1] * VFilter[1]) +
+          (src_ptr[2] * VFilter[2]) +
+          (src_ptr[3] * VFilter[3]) +
+          (src_ptr[4] * VFilter[4]) +
+          (src_ptr[5] * VFilter[5]) +
+          (src_ptr[6] * VFilter[6]) +
+          (src_ptr[7] * VFilter[7]) +
+          (VP9_FILTER_WEIGHT >> 1);  // Rounding
+
+      // Normalize back to 0-255...
+      *dst_ptr++ = clip_pixel(temp >> VP9_FILTER_SHIFT);
+      src_ptr += intermediate_height;
+    }
+    src_ptr += intermediate_next_stride;
+    dst_ptr += dst_next_row_stride;
+  }
+}
+
+void block2d_average_c(uint8_t *src,
+                       unsigned int src_stride,
+                       uint8_t *output_ptr,
+                       unsigned int output_stride,
+                       unsigned int output_width,
+                       unsigned int output_height) {
+  unsigned int i, j;
+  for (i = 0; i < output_height; ++i) {
+    for (j = 0; j < output_width; ++j) {
+      output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1;
+    }
+    output_ptr += output_stride;
+  }
+}
+
+void filter_average_block2d_8_c(const uint8_t *src_ptr,
+                                const unsigned int src_stride,
+                                const int16_t *HFilter,
+                                const int16_t *VFilter,
+                                uint8_t *dst_ptr,
+                                unsigned int dst_stride,
+                                unsigned int output_width,
+                                unsigned int output_height) {
+  uint8_t tmp[kMaxDimension * kMaxDimension];
+
+  assert(output_width <= kMaxDimension);
+  assert(output_height <= kMaxDimension);
+  filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, tmp, 64,
+                     output_width, output_height);
+  block2d_average_c(tmp, 64, dst_ptr, dst_stride,
+                    output_width, output_height);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void highbd_filter_block2d_8_c(const uint16_t *src_ptr,
+                               const unsigned int src_stride,
+                               const int16_t *HFilter,
+                               const int16_t *VFilter,
+                               uint16_t *dst_ptr,
+                               unsigned int dst_stride,
+                               unsigned int output_width,
+                               unsigned int output_height,
+                               int bd) {
+  // Between passes, we use an intermediate buffer whose height is extended to
+  // have enough horizontally filtered values as input for the vertical pass.
+  // This buffer is allocated to be big enough for the largest block type we
+  // support.
+  const int kInterp_Extend = 4;
+  const unsigned int intermediate_height =
+      (kInterp_Extend - 1) + output_height + kInterp_Extend;
+
+  /* Size of intermediate_buffer is max_intermediate_height * filter_max_width,
+   * where max_intermediate_height = (kInterp_Extend - 1) + filter_max_height
+   *                                 + kInterp_Extend
+   *                               = 3 + 16 + 4
+   *                               = 23
+   * and filter_max_width = 16
+   */
+  uint16_t intermediate_buffer[71 * kMaxDimension];
+  const int intermediate_next_stride =
+      1 - static_cast<int>(intermediate_height * output_width);
+
+  // Horizontal pass (src -> transposed intermediate).
+  {
+    uint16_t *output_ptr = intermediate_buffer;
+    const int src_next_row_stride = src_stride - output_width;
+    unsigned int i, j;
+    src_ptr -= (kInterp_Extend - 1) * src_stride + (kInterp_Extend - 1);
+    for (i = 0; i < intermediate_height; ++i) {
+      for (j = 0; j < output_width; ++j) {
+        // Apply filter...
+        const int temp = (src_ptr[0] * HFilter[0]) +
+                         (src_ptr[1] * HFilter[1]) +
+                         (src_ptr[2] * HFilter[2]) +
+                         (src_ptr[3] * HFilter[3]) +
+                         (src_ptr[4] * HFilter[4]) +
+                         (src_ptr[5] * HFilter[5]) +
+                         (src_ptr[6] * HFilter[6]) +
+                         (src_ptr[7] * HFilter[7]) +
+                         (VP9_FILTER_WEIGHT >> 1);  // Rounding
+
+        // Normalize back to 0-255...
+        *output_ptr = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd);
+        ++src_ptr;
+        output_ptr += intermediate_height;
+      }
+      src_ptr += src_next_row_stride;
+      output_ptr += intermediate_next_stride;
+    }
+  }
+
+  // Vertical pass (transposed intermediate -> dst).
+  {
+    uint16_t *src_ptr = intermediate_buffer;
+    const int dst_next_row_stride = dst_stride - output_width;
+    unsigned int i, j;
+    for (i = 0; i < output_height; ++i) {
+      for (j = 0; j < output_width; ++j) {
+        // Apply filter...
+        const int temp = (src_ptr[0] * VFilter[0]) +
+                         (src_ptr[1] * VFilter[1]) +
+                         (src_ptr[2] * VFilter[2]) +
+                         (src_ptr[3] * VFilter[3]) +
+                         (src_ptr[4] * VFilter[4]) +
+                         (src_ptr[5] * VFilter[5]) +
+                         (src_ptr[6] * VFilter[6]) +
+                         (src_ptr[7] * VFilter[7]) +
+                         (VP9_FILTER_WEIGHT >> 1);  // Rounding
+
+        // Normalize back to 0-255...
+        *dst_ptr++ = clip_pixel_highbd(temp >> VP9_FILTER_SHIFT, bd);
+        src_ptr += intermediate_height;
+      }
+      src_ptr += intermediate_next_stride;
+      dst_ptr += dst_next_row_stride;
+    }
+  }
+}
+
+void highbd_block2d_average_c(uint16_t *src,
+                              unsigned int src_stride,
+                              uint16_t *output_ptr,
+                              unsigned int output_stride,
+                              unsigned int output_width,
+                              unsigned int output_height) {
+  unsigned int i, j;
+  for (i = 0; i < output_height; ++i) {
+    for (j = 0; j < output_width; ++j) {
+      output_ptr[j] = (output_ptr[j] + src[i * src_stride + j] + 1) >> 1;
+    }
+    output_ptr += output_stride;
+  }
+}
+
+void highbd_filter_average_block2d_8_c(const uint16_t *src_ptr,
+                                       const unsigned int src_stride,
+                                       const int16_t *HFilter,
+                                       const int16_t *VFilter,
+                                       uint16_t *dst_ptr,
+                                       unsigned int dst_stride,
+                                       unsigned int output_width,
+                                       unsigned int output_height,
+                                       int bd) {
+  uint16_t tmp[kMaxDimension * kMaxDimension];
+
+  assert(output_width <= kMaxDimension);
+  assert(output_height <= kMaxDimension);
+  highbd_filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter, tmp, 64,
+                            output_width, output_height, bd);
+  highbd_block2d_average_c(tmp, 64, dst_ptr, dst_stride,
+                           output_width, output_height);
+}
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+class ConvolveTest : public ::testing::TestWithParam<ConvolveParam> {
+ public:
+  static void SetUpTestCase() {
+    // Force input_ to be unaligned, output to be 16 byte aligned.
+    input_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kInputBufferSize + 1)) + 1;
+    output_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kOutputBufferSize));
+    output_ref_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kOutputBufferSize));
+#if CONFIG_VP9_HIGHBITDEPTH
+    input16_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment,
+                     (kInputBufferSize + 1) * sizeof(uint16_t))) + 1;
+    output16_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t)));
+    output16_ref_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment, (kOutputBufferSize) * sizeof(uint16_t)));
+#endif
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+  static void TearDownTestCase() {
+    vpx_free(input_ - 1);
+    input_ = NULL;
+    vpx_free(output_);
+    output_ = NULL;
+    vpx_free(output_ref_);
+    output_ref_ = NULL;
+#if CONFIG_VP9_HIGHBITDEPTH
+    vpx_free(input16_ - 1);
+    input16_ = NULL;
+    vpx_free(output16_);
+    output16_ = NULL;
+    vpx_free(output16_ref_);
+    output16_ref_ = NULL;
+#endif
+  }
+
+ protected:
+  static const int kDataAlignment = 16;
+  static const int kOuterBlockSize = 256;
+  static const int kInputStride = kOuterBlockSize;
+  static const int kOutputStride = kOuterBlockSize;
+  static const int kInputBufferSize = kOuterBlockSize * kOuterBlockSize;
+  static const int kOutputBufferSize = kOuterBlockSize * kOuterBlockSize;
+
+  int Width() const { return GET_PARAM(0); }
+  int Height() const { return GET_PARAM(1); }
+  int BorderLeft() const {
+    const int center = (kOuterBlockSize - Width()) / 2;
+    return (center + (kDataAlignment - 1)) & ~(kDataAlignment - 1);
+  }
+  int BorderTop() const { return (kOuterBlockSize - Height()) / 2; }
+
+  bool IsIndexInBorder(int i) {
+    return (i < BorderTop() * kOuterBlockSize ||
+            i >= (BorderTop() + Height()) * kOuterBlockSize ||
+            i % kOuterBlockSize < BorderLeft() ||
+            i % kOuterBlockSize >= (BorderLeft() + Width()));
+  }
+
+  virtual void SetUp() {
+    UUT_ = GET_PARAM(2);
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ != 0)
+      mask_ = (1 << UUT_->use_highbd_) - 1;
+    else
+      mask_ = 255;
+#endif
+    /* Set up guard blocks for an inner block centered in the outer block */
+    for (int i = 0; i < kOutputBufferSize; ++i) {
+      if (IsIndexInBorder(i))
+        output_[i] = 255;
+      else
+        output_[i] = 0;
+    }
+
+    ::libvpx_test::ACMRandom prng;
+    for (int i = 0; i < kInputBufferSize; ++i) {
+      if (i & 1) {
+        input_[i] = 255;
+#if CONFIG_VP9_HIGHBITDEPTH
+        input16_[i] = mask_;
+#endif
+      } else {
+        input_[i] = prng.Rand8Extremes();
+#if CONFIG_VP9_HIGHBITDEPTH
+        input16_[i] = prng.Rand16() & mask_;
+#endif
+      }
+    }
+  }
+
+  void SetConstantInput(int value) {
+    memset(input_, value, kInputBufferSize);
+#if CONFIG_VP9_HIGHBITDEPTH
+    vpx_memset16(input16_, value, kInputBufferSize);
+#endif
+  }
+
+  void CopyOutputToRef() {
+    memcpy(output_ref_, output_, kOutputBufferSize);
+#if CONFIG_VP9_HIGHBITDEPTH
+    memcpy(output16_ref_, output16_, kOutputBufferSize);
+#endif
+  }
+
+  void CheckGuardBlocks() {
+    for (int i = 0; i < kOutputBufferSize; ++i) {
+      if (IsIndexInBorder(i))
+        EXPECT_EQ(255, output_[i]);
+    }
+  }
+
+  uint8_t *input() const {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      return input_ + BorderTop() * kOuterBlockSize + BorderLeft();
+    } else {
+      return CONVERT_TO_BYTEPTR(input16_ + BorderTop() * kOuterBlockSize +
+                                BorderLeft());
+    }
+#else
+    return input_ + BorderTop() * kOuterBlockSize + BorderLeft();
+#endif
+  }
+
+  uint8_t *output() const {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      return output_ + BorderTop() * kOuterBlockSize + BorderLeft();
+    } else {
+      return CONVERT_TO_BYTEPTR(output16_ + BorderTop() * kOuterBlockSize +
+                                BorderLeft());
+    }
+#else
+    return output_ + BorderTop() * kOuterBlockSize + BorderLeft();
+#endif
+  }
+
+  uint8_t *output_ref() const {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      return output_ref_ + BorderTop() * kOuterBlockSize + BorderLeft();
+    } else {
+      return CONVERT_TO_BYTEPTR(output16_ref_ + BorderTop() * kOuterBlockSize +
+                                BorderLeft());
+    }
+#else
+    return output_ref_ + BorderTop() * kOuterBlockSize + BorderLeft();
+#endif
+  }
+
+  uint16_t lookup(uint8_t *list, int index) const {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      return list[index];
+    } else {
+      return CONVERT_TO_SHORTPTR(list)[index];
+    }
+#else
+    return list[index];
+#endif
+  }
+
+  void assign_val(uint8_t *list, int index, uint16_t val) const {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      list[index] = (uint8_t) val;
+    } else {
+      CONVERT_TO_SHORTPTR(list)[index] = val;
+    }
+#else
+    list[index] = (uint8_t) val;
+#endif
+  }
+
+  void wrapper_filter_average_block2d_8_c(const uint8_t *src_ptr,
+                                          const unsigned int src_stride,
+                                          const int16_t *HFilter,
+                                          const int16_t *VFilter,
+                                          uint8_t *dst_ptr,
+                                          unsigned int dst_stride,
+                                          unsigned int output_width,
+                                          unsigned int output_height) {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      filter_average_block2d_8_c(src_ptr, src_stride, HFilter, VFilter,
+                                 dst_ptr, dst_stride, output_width,
+                                 output_height);
+    } else {
+      highbd_filter_average_block2d_8_c(CONVERT_TO_SHORTPTR(src_ptr),
+                                        src_stride, HFilter, VFilter,
+                                        CONVERT_TO_SHORTPTR(dst_ptr),
+                                        dst_stride, output_width, output_height,
+                                        UUT_->use_highbd_);
+    }
+#else
+    filter_average_block2d_8_c(src_ptr, src_stride, HFilter, VFilter,
+                               dst_ptr, dst_stride, output_width,
+                               output_height);
+#endif
+  }
+
+  void wrapper_filter_block2d_8_c(const uint8_t *src_ptr,
+                                  const unsigned int src_stride,
+                                  const int16_t *HFilter,
+                                  const int16_t *VFilter,
+                                  uint8_t *dst_ptr,
+                                  unsigned int dst_stride,
+                                  unsigned int output_width,
+                                  unsigned int output_height) {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (UUT_->use_highbd_ == 0) {
+      filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter,
+                         dst_ptr, dst_stride, output_width, output_height);
+    } else {
+      highbd_filter_block2d_8_c(CONVERT_TO_SHORTPTR(src_ptr), src_stride,
+                                HFilter, VFilter,
+                                CONVERT_TO_SHORTPTR(dst_ptr), dst_stride,
+                                output_width, output_height, UUT_->use_highbd_);
+    }
+#else
+    filter_block2d_8_c(src_ptr, src_stride, HFilter, VFilter,
+                       dst_ptr, dst_stride, output_width, output_height);
+#endif
+  }
+
+  const ConvolveFunctions* UUT_;
+  static uint8_t* input_;
+  static uint8_t* output_;
+  static uint8_t* output_ref_;
+#if CONFIG_VP9_HIGHBITDEPTH
+  static uint16_t* input16_;
+  static uint16_t* output16_;
+  static uint16_t* output16_ref_;
+  int mask_;
+#endif
+};
+
+uint8_t* ConvolveTest::input_ = NULL;
+uint8_t* ConvolveTest::output_ = NULL;
+uint8_t* ConvolveTest::output_ref_ = NULL;
+#if CONFIG_VP9_HIGHBITDEPTH
+uint16_t* ConvolveTest::input16_ = NULL;
+uint16_t* ConvolveTest::output16_ = NULL;
+uint16_t* ConvolveTest::output16_ref_ = NULL;
+#endif
+
+TEST_P(ConvolveTest, GuardBlocks) {
+  CheckGuardBlocks();
+}
+
+TEST_P(ConvolveTest, Copy) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+
+  ASM_REGISTER_STATE_CHECK(
+      UUT_->copy_(in, kInputStride, out, kOutputStride, NULL, 0, NULL, 0,
+                  Width(), Height()));
+
+  CheckGuardBlocks();
+
+  for (int y = 0; y < Height(); ++y)
+    for (int x = 0; x < Width(); ++x)
+      ASSERT_EQ(lookup(out, y * kOutputStride + x),
+                lookup(in, y * kInputStride + x))
+          << "(" << x << "," << y << ")";
+}
+
+TEST_P(ConvolveTest, Avg) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+  uint8_t* const out_ref = output_ref();
+  CopyOutputToRef();
+
+  ASM_REGISTER_STATE_CHECK(
+      UUT_->avg_(in, kInputStride, out, kOutputStride, NULL, 0, NULL, 0,
+                Width(), Height()));
+
+  CheckGuardBlocks();
+
+  for (int y = 0; y < Height(); ++y)
+    for (int x = 0; x < Width(); ++x)
+      ASSERT_EQ(lookup(out, y * kOutputStride + x),
+                ROUND_POWER_OF_TWO(lookup(in, y * kInputStride + x) +
+                                   lookup(out_ref, y * kOutputStride + x), 1))
+          << "(" << x << "," << y << ")";
+}
+
+TEST_P(ConvolveTest, CopyHoriz) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+  DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0};
+
+  ASM_REGISTER_STATE_CHECK(
+      UUT_->sh8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8, 16,
+                 Width(), Height()));
+
+  CheckGuardBlocks();
+
+  for (int y = 0; y < Height(); ++y)
+    for (int x = 0; x < Width(); ++x)
+      ASSERT_EQ(lookup(out, y * kOutputStride + x),
+                lookup(in, y * kInputStride + x))
+          << "(" << x << "," << y << ")";
+}
+
+TEST_P(ConvolveTest, CopyVert) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+  DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0};
+
+  ASM_REGISTER_STATE_CHECK(
+      UUT_->sv8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8, 16,
+                 Width(), Height()));
+
+  CheckGuardBlocks();
+
+  for (int y = 0; y < Height(); ++y)
+    for (int x = 0; x < Width(); ++x)
+      ASSERT_EQ(lookup(out, y * kOutputStride + x),
+                lookup(in, y * kInputStride + x))
+          << "(" << x << "," << y << ")";
+}
+
+TEST_P(ConvolveTest, Copy2D) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+  DECLARE_ALIGNED(256, const int16_t, filter8[8]) = {0, 0, 0, 128, 0, 0, 0, 0};
+
+  ASM_REGISTER_STATE_CHECK(
+      UUT_->shv8_(in, kInputStride, out, kOutputStride, filter8, 16, filter8,
+                  16, Width(), Height()));
+
+  CheckGuardBlocks();
+
+  for (int y = 0; y < Height(); ++y)
+    for (int x = 0; x < Width(); ++x)
+      ASSERT_EQ(lookup(out, y * kOutputStride + x),
+                lookup(in, y * kInputStride + x))
+          << "(" << x << "," << y << ")";
+}
+
+const int kNumFilterBanks = 4;
+const int kNumFilters = 16;
+
+TEST(ConvolveTest, FiltersWontSaturateWhenAddedPairwise) {
+  for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+    const InterpKernel *filters =
+        vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+    for (int i = 0; i < kNumFilters; i++) {
+      const int p0 = filters[i][0] + filters[i][1];
+      const int p1 = filters[i][2] + filters[i][3];
+      const int p2 = filters[i][4] + filters[i][5];
+      const int p3 = filters[i][6] + filters[i][7];
+      EXPECT_LE(p0, 128);
+      EXPECT_LE(p1, 128);
+      EXPECT_LE(p2, 128);
+      EXPECT_LE(p3, 128);
+      EXPECT_LE(p0 + p3, 128);
+      EXPECT_LE(p0 + p3 + p1, 128);
+      EXPECT_LE(p0 + p3 + p1 + p2, 128);
+      EXPECT_EQ(p0 + p1 + p2 + p3, 128);
+    }
+  }
+}
+
+const int16_t kInvalidFilter[8] = { 0 };
+
+TEST_P(ConvolveTest, MatchesReferenceSubpixelFilter) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+#if CONFIG_VP9_HIGHBITDEPTH
+  uint8_t ref8[kOutputStride * kMaxDimension];
+  uint16_t ref16[kOutputStride * kMaxDimension];
+  uint8_t* ref;
+  if (UUT_->use_highbd_ == 0) {
+    ref = ref8;
+  } else {
+    ref = CONVERT_TO_BYTEPTR(ref16);
+  }
+#else
+  uint8_t ref[kOutputStride * kMaxDimension];
+#endif
+
+  for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+    const InterpKernel *filters =
+        vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+
+    for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) {
+      for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) {
+        wrapper_filter_block2d_8_c(in, kInputStride,
+                                   filters[filter_x], filters[filter_y],
+                                   ref, kOutputStride,
+                                   Width(), Height());
+
+        if (filter_x && filter_y)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->hv8_(in, kInputStride, out, kOutputStride,
+                         filters[filter_x], 16, filters[filter_y], 16,
+                         Width(), Height()));
+        else if (filter_y)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->v8_(in, kInputStride, out, kOutputStride,
+                        kInvalidFilter, 16, filters[filter_y], 16,
+                        Width(), Height()));
+        else if (filter_x)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->h8_(in, kInputStride, out, kOutputStride,
+                        filters[filter_x], 16, kInvalidFilter, 16,
+                        Width(), Height()));
+        else
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->copy_(in, kInputStride, out, kOutputStride,
+                          kInvalidFilter, 0, kInvalidFilter, 0,
+                          Width(), Height()));
+
+        CheckGuardBlocks();
+
+        for (int y = 0; y < Height(); ++y)
+          for (int x = 0; x < Width(); ++x)
+            ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+                      lookup(out, y * kOutputStride + x))
+                << "mismatch at (" << x << "," << y << "), "
+                << "filters (" << filter_bank << ","
+                << filter_x << "," << filter_y << ")";
+      }
+    }
+  }
+}
+
+TEST_P(ConvolveTest, MatchesReferenceAveragingSubpixelFilter) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+#if CONFIG_VP9_HIGHBITDEPTH
+  uint8_t ref8[kOutputStride * kMaxDimension];
+  uint16_t ref16[kOutputStride * kMaxDimension];
+  uint8_t* ref;
+  if (UUT_->use_highbd_ == 0) {
+    ref = ref8;
+  } else {
+    ref = CONVERT_TO_BYTEPTR(ref16);
+  }
+#else
+  uint8_t ref[kOutputStride * kMaxDimension];
+#endif
+
+  // Populate ref and out with some random data
+  ::libvpx_test::ACMRandom prng;
+  for (int y = 0; y < Height(); ++y) {
+    for (int x = 0; x < Width(); ++x) {
+      uint16_t r;
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) {
+        r = prng.Rand8Extremes();
+      } else {
+        r = prng.Rand16() & mask_;
+      }
+#else
+      r = prng.Rand8Extremes();
+#endif
+
+      assign_val(out, y * kOutputStride + x, r);
+      assign_val(ref, y * kOutputStride + x, r);
+    }
+  }
+
+  for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+    const InterpKernel *filters =
+        vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+
+    for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) {
+      for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) {
+        wrapper_filter_average_block2d_8_c(in, kInputStride,
+                                           filters[filter_x], filters[filter_y],
+                                           ref, kOutputStride,
+                                           Width(), Height());
+
+        if (filter_x && filter_y)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->hv8_avg_(in, kInputStride, out, kOutputStride,
+                             filters[filter_x], 16, filters[filter_y], 16,
+                             Width(), Height()));
+        else if (filter_y)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->v8_avg_(in, kInputStride, out, kOutputStride,
+                            kInvalidFilter, 16, filters[filter_y], 16,
+                            Width(), Height()));
+        else if (filter_x)
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->h8_avg_(in, kInputStride, out, kOutputStride,
+                            filters[filter_x], 16, kInvalidFilter, 16,
+                            Width(), Height()));
+        else
+          ASM_REGISTER_STATE_CHECK(
+              UUT_->avg_(in, kInputStride, out, kOutputStride,
+                          kInvalidFilter, 0, kInvalidFilter, 0,
+                          Width(), Height()));
+
+        CheckGuardBlocks();
+
+        for (int y = 0; y < Height(); ++y)
+          for (int x = 0; x < Width(); ++x)
+            ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+                      lookup(out, y * kOutputStride + x))
+                << "mismatch at (" << x << "," << y << "), "
+                << "filters (" << filter_bank << ","
+                << filter_x << "," << filter_y << ")";
+      }
+    }
+  }
+}
+
+TEST_P(ConvolveTest, FilterExtremes) {
+  uint8_t *const in = input();
+  uint8_t *const out = output();
+#if CONFIG_VP9_HIGHBITDEPTH
+  uint8_t ref8[kOutputStride * kMaxDimension];
+  uint16_t ref16[kOutputStride * kMaxDimension];
+  uint8_t *ref;
+  if (UUT_->use_highbd_ == 0) {
+    ref = ref8;
+  } else {
+    ref = CONVERT_TO_BYTEPTR(ref16);
+  }
+#else
+  uint8_t ref[kOutputStride * kMaxDimension];
+#endif
+
+  // Populate ref and out with some random data
+  ::libvpx_test::ACMRandom prng;
+  for (int y = 0; y < Height(); ++y) {
+    for (int x = 0; x < Width(); ++x) {
+      uint16_t r;
+#if CONFIG_VP9_HIGHBITDEPTH
+      if (UUT_->use_highbd_ == 0 || UUT_->use_highbd_ == 8) {
+        r = prng.Rand8Extremes();
+      } else {
+        r = prng.Rand16() & mask_;
+      }
+#else
+      r = prng.Rand8Extremes();
+#endif
+      assign_val(out, y * kOutputStride + x, r);
+      assign_val(ref, y * kOutputStride + x, r);
+    }
+  }
+
+  for (int axis = 0; axis < 2; axis++) {
+    int seed_val = 0;
+    while (seed_val < 256) {
+      for (int y = 0; y < 8; ++y) {
+        for (int x = 0; x < 8; ++x) {
+#if CONFIG_VP9_HIGHBITDEPTH
+            assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1,
+                       ((seed_val >> (axis ? y : x)) & 1) * mask_);
+#else
+            assign_val(in, y * kOutputStride + x - SUBPEL_TAPS / 2 + 1,
+                       ((seed_val >> (axis ? y : x)) & 1) * 255);
+#endif
+          if (axis) seed_val++;
+        }
+        if (axis)
+          seed_val-= 8;
+        else
+          seed_val++;
+      }
+      if (axis) seed_val += 8;
+
+      for (int filter_bank = 0; filter_bank < kNumFilterBanks; ++filter_bank) {
+        const InterpKernel *filters =
+            vp9_filter_kernels[static_cast<INTERP_FILTER>(filter_bank)];
+        for (int filter_x = 0; filter_x < kNumFilters; ++filter_x) {
+          for (int filter_y = 0; filter_y < kNumFilters; ++filter_y) {
+            wrapper_filter_block2d_8_c(in, kInputStride,
+                                       filters[filter_x], filters[filter_y],
+                                       ref, kOutputStride,
+                                       Width(), Height());
+            if (filter_x && filter_y)
+              ASM_REGISTER_STATE_CHECK(
+                  UUT_->hv8_(in, kInputStride, out, kOutputStride,
+                             filters[filter_x], 16, filters[filter_y], 16,
+                             Width(), Height()));
+            else if (filter_y)
+              ASM_REGISTER_STATE_CHECK(
+                  UUT_->v8_(in, kInputStride, out, kOutputStride,
+                            kInvalidFilter, 16, filters[filter_y], 16,
+                            Width(), Height()));
+            else if (filter_x)
+              ASM_REGISTER_STATE_CHECK(
+                  UUT_->h8_(in, kInputStride, out, kOutputStride,
+                            filters[filter_x], 16, kInvalidFilter, 16,
+                            Width(), Height()));
+            else
+              ASM_REGISTER_STATE_CHECK(
+                  UUT_->copy_(in, kInputStride, out, kOutputStride,
+                              kInvalidFilter, 0, kInvalidFilter, 0,
+                              Width(), Height()));
+
+            for (int y = 0; y < Height(); ++y)
+              for (int x = 0; x < Width(); ++x)
+                ASSERT_EQ(lookup(ref, y * kOutputStride + x),
+                          lookup(out, y * kOutputStride + x))
+                    << "mismatch at (" << x << "," << y << "), "
+                    << "filters (" << filter_bank << ","
+                    << filter_x << "," << filter_y << ")";
+          }
+        }
+      }
+    }
+  }
+}
+
+/* This test exercises that enough rows and columns are filtered with every
+   possible initial fractional positions and scaling steps. */
+TEST_P(ConvolveTest, CheckScalingFiltering) {
+  uint8_t* const in = input();
+  uint8_t* const out = output();
+  const InterpKernel *const eighttap = vp9_filter_kernels[EIGHTTAP];
+
+  SetConstantInput(127);
+
+  for (int frac = 0; frac < 16; ++frac) {
+    for (int step = 1; step <= 32; ++step) {
+      /* Test the horizontal and vertical filters in combination. */
+      ASM_REGISTER_STATE_CHECK(UUT_->shv8_(in, kInputStride, out, kOutputStride,
+                                           eighttap[frac], step,
+                                           eighttap[frac], step,
+                                           Width(), Height()));
+
+      CheckGuardBlocks();
+
+      for (int y = 0; y < Height(); ++y) {
+        for (int x = 0; x < Width(); ++x) {
+          ASSERT_EQ(lookup(in, y * kInputStride + x),
+                    lookup(out, y * kOutputStride + x))
+              << "x == " << x << ", y == " << y
+              << ", frac == " << frac << ", step == " << step;
+        }
+      }
+    }
+  }
+}
+
+using std::tr1::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+#define WRAP(func, bd) \
+void wrap_ ## func ## _ ## bd(const uint8_t *src, ptrdiff_t src_stride, \
+                              uint8_t *dst, ptrdiff_t dst_stride, \
+                              const int16_t *filter_x, \
+                              int filter_x_stride, \
+                              const int16_t *filter_y, \
+                              int filter_y_stride, \
+                              int w, int h) { \
+  vpx_highbd_ ## func(src, src_stride, dst, dst_stride, filter_x, \
+                      filter_x_stride, filter_y, filter_y_stride, \
+                      w, h, bd); \
+}
+#if HAVE_SSE2 && ARCH_X86_64
+#if CONFIG_USE_X86INC
+WRAP(convolve_copy_sse2, 8)
+WRAP(convolve_avg_sse2, 8)
+WRAP(convolve_copy_sse2, 10)
+WRAP(convolve_avg_sse2, 10)
+WRAP(convolve_copy_sse2, 12)
+WRAP(convolve_avg_sse2, 12)
+#endif  // CONFIG_USE_X86INC
+WRAP(convolve8_horiz_sse2, 8)
+WRAP(convolve8_avg_horiz_sse2, 8)
+WRAP(convolve8_vert_sse2, 8)
+WRAP(convolve8_avg_vert_sse2, 8)
+WRAP(convolve8_sse2, 8)
+WRAP(convolve8_avg_sse2, 8)
+WRAP(convolve8_horiz_sse2, 10)
+WRAP(convolve8_avg_horiz_sse2, 10)
+WRAP(convolve8_vert_sse2, 10)
+WRAP(convolve8_avg_vert_sse2, 10)
+WRAP(convolve8_sse2, 10)
+WRAP(convolve8_avg_sse2, 10)
+WRAP(convolve8_horiz_sse2, 12)
+WRAP(convolve8_avg_horiz_sse2, 12)
+WRAP(convolve8_vert_sse2, 12)
+WRAP(convolve8_avg_vert_sse2, 12)
+WRAP(convolve8_sse2, 12)
+WRAP(convolve8_avg_sse2, 12)
+#endif  // HAVE_SSE2 && ARCH_X86_64
+
+WRAP(convolve_copy_c, 8)
+WRAP(convolve_avg_c, 8)
+WRAP(convolve8_horiz_c, 8)
+WRAP(convolve8_avg_horiz_c, 8)
+WRAP(convolve8_vert_c, 8)
+WRAP(convolve8_avg_vert_c, 8)
+WRAP(convolve8_c, 8)
+WRAP(convolve8_avg_c, 8)
+WRAP(convolve_copy_c, 10)
+WRAP(convolve_avg_c, 10)
+WRAP(convolve8_horiz_c, 10)
+WRAP(convolve8_avg_horiz_c, 10)
+WRAP(convolve8_vert_c, 10)
+WRAP(convolve8_avg_vert_c, 10)
+WRAP(convolve8_c, 10)
+WRAP(convolve8_avg_c, 10)
+WRAP(convolve_copy_c, 12)
+WRAP(convolve_avg_c, 12)
+WRAP(convolve8_horiz_c, 12)
+WRAP(convolve8_avg_horiz_c, 12)
+WRAP(convolve8_vert_c, 12)
+WRAP(convolve8_avg_vert_c, 12)
+WRAP(convolve8_c, 12)
+WRAP(convolve8_avg_c, 12)
+#undef WRAP
+
+const ConvolveFunctions convolve8_c(
+    wrap_convolve_copy_c_8, wrap_convolve_avg_c_8,
+    wrap_convolve8_horiz_c_8, wrap_convolve8_avg_horiz_c_8,
+    wrap_convolve8_vert_c_8, wrap_convolve8_avg_vert_c_8,
+    wrap_convolve8_c_8, wrap_convolve8_avg_c_8,
+    wrap_convolve8_horiz_c_8, wrap_convolve8_avg_horiz_c_8,
+    wrap_convolve8_vert_c_8, wrap_convolve8_avg_vert_c_8,
+    wrap_convolve8_c_8, wrap_convolve8_avg_c_8, 8);
+const ConvolveFunctions convolve10_c(
+    wrap_convolve_copy_c_10, wrap_convolve_avg_c_10,
+    wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10,
+    wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10,
+    wrap_convolve8_c_10, wrap_convolve8_avg_c_10,
+    wrap_convolve8_horiz_c_10, wrap_convolve8_avg_horiz_c_10,
+    wrap_convolve8_vert_c_10, wrap_convolve8_avg_vert_c_10,
+    wrap_convolve8_c_10, wrap_convolve8_avg_c_10, 10);
+const ConvolveFunctions convolve12_c(
+    wrap_convolve_copy_c_12, wrap_convolve_avg_c_12,
+    wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12,
+    wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12,
+    wrap_convolve8_c_12, wrap_convolve8_avg_c_12,
+    wrap_convolve8_horiz_c_12, wrap_convolve8_avg_horiz_c_12,
+    wrap_convolve8_vert_c_12, wrap_convolve8_avg_vert_c_12,
+    wrap_convolve8_c_12, wrap_convolve8_avg_c_12, 12);
+const ConvolveParam kArrayConvolve_c[] = {
+    ALL_SIZES(convolve8_c),
+    ALL_SIZES(convolve10_c),
+    ALL_SIZES(convolve12_c)
+};
+
+#else
+const ConvolveFunctions convolve8_c(
+    vpx_convolve_copy_c, vpx_convolve_avg_c,
+    vpx_convolve8_horiz_c, vpx_convolve8_avg_horiz_c,
+    vpx_convolve8_vert_c, vpx_convolve8_avg_vert_c,
+    vpx_convolve8_c, vpx_convolve8_avg_c,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+const ConvolveParam kArrayConvolve_c[] = { ALL_SIZES(convolve8_c) };
+#endif
+INSTANTIATE_TEST_CASE_P(C, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve_c));
+
+#if HAVE_SSE2 && ARCH_X86_64
+#if CONFIG_VP9_HIGHBITDEPTH
+const ConvolveFunctions convolve8_sse2(
+#if CONFIG_USE_X86INC
+    wrap_convolve_copy_sse2_8, wrap_convolve_avg_sse2_8,
+#else
+    wrap_convolve_copy_c_8, wrap_convolve_avg_c_8,
+#endif  // CONFIG_USE_X86INC
+    wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8,
+    wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
+    wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8,
+    wrap_convolve8_horiz_sse2_8, wrap_convolve8_avg_horiz_sse2_8,
+    wrap_convolve8_vert_sse2_8, wrap_convolve8_avg_vert_sse2_8,
+    wrap_convolve8_sse2_8, wrap_convolve8_avg_sse2_8, 8);
+const ConvolveFunctions convolve10_sse2(
+#if CONFIG_USE_X86INC
+    wrap_convolve_copy_sse2_10, wrap_convolve_avg_sse2_10,
+#else
+    wrap_convolve_copy_c_10, wrap_convolve_avg_c_10,
+#endif  // CONFIG_USE_X86INC
+    wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10,
+    wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
+    wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10,
+    wrap_convolve8_horiz_sse2_10, wrap_convolve8_avg_horiz_sse2_10,
+    wrap_convolve8_vert_sse2_10, wrap_convolve8_avg_vert_sse2_10,
+    wrap_convolve8_sse2_10, wrap_convolve8_avg_sse2_10, 10);
+const ConvolveFunctions convolve12_sse2(
+#if CONFIG_USE_X86INC
+    wrap_convolve_copy_sse2_12, wrap_convolve_avg_sse2_12,
+#else
+    wrap_convolve_copy_c_12, wrap_convolve_avg_c_12,
+#endif  // CONFIG_USE_X86INC
+    wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12,
+    wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12,
+    wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12,
+    wrap_convolve8_horiz_sse2_12, wrap_convolve8_avg_horiz_sse2_12,
+    wrap_convolve8_vert_sse2_12, wrap_convolve8_avg_vert_sse2_12,
+    wrap_convolve8_sse2_12, wrap_convolve8_avg_sse2_12, 12);
+const ConvolveParam kArrayConvolve_sse2[] = {
+    ALL_SIZES(convolve8_sse2),
+    ALL_SIZES(convolve10_sse2),
+    ALL_SIZES(convolve12_sse2)
+};
+#else
+const ConvolveFunctions convolve8_sse2(
+#if CONFIG_USE_X86INC
+    vpx_convolve_copy_sse2, vpx_convolve_avg_sse2,
+#else
+    vpx_convolve_copy_c, vpx_convolve_avg_c,
+#endif  // CONFIG_USE_X86INC
+    vpx_convolve8_horiz_sse2, vpx_convolve8_avg_horiz_sse2,
+    vpx_convolve8_vert_sse2, vpx_convolve8_avg_vert_sse2,
+    vpx_convolve8_sse2, vpx_convolve8_avg_sse2,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve_sse2[] = { ALL_SIZES(convolve8_sse2) };
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(SSE2, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve_sse2));
+#endif
+
+#if HAVE_SSSE3
+const ConvolveFunctions convolve8_ssse3(
+    vpx_convolve_copy_c, vpx_convolve_avg_c,
+    vpx_convolve8_horiz_ssse3, vpx_convolve8_avg_horiz_ssse3,
+    vpx_convolve8_vert_ssse3, vpx_convolve8_avg_vert_ssse3,
+    vpx_convolve8_ssse3, vpx_convolve8_avg_ssse3,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_ssse3, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_ssse3[] = { ALL_SIZES(convolve8_ssse3) };
+INSTANTIATE_TEST_CASE_P(SSSE3, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve8_ssse3));
+#endif
+
+#if HAVE_AVX2 && HAVE_SSSE3
+const ConvolveFunctions convolve8_avx2(
+    vpx_convolve_copy_c, vpx_convolve_avg_c,
+    vpx_convolve8_horiz_avx2, vpx_convolve8_avg_horiz_ssse3,
+    vpx_convolve8_vert_avx2, vpx_convolve8_avg_vert_ssse3,
+    vpx_convolve8_avx2, vpx_convolve8_avg_ssse3,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_avx2[] = { ALL_SIZES(convolve8_avx2) };
+INSTANTIATE_TEST_CASE_P(AVX2, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve8_avx2));
+#endif  // HAVE_AVX2 && HAVE_SSSE3
+
+#if HAVE_NEON
+#if HAVE_NEON_ASM
+const ConvolveFunctions convolve8_neon(
+    vpx_convolve_copy_neon, vpx_convolve_avg_neon,
+    vpx_convolve8_horiz_neon, vpx_convolve8_avg_horiz_neon,
+    vpx_convolve8_vert_neon, vpx_convolve8_avg_vert_neon,
+    vpx_convolve8_neon, vpx_convolve8_avg_neon,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+#else  // HAVE_NEON
+const ConvolveFunctions convolve8_neon(
+    vpx_convolve_copy_neon, vpx_convolve_avg_neon,
+    vpx_convolve8_horiz_neon, vpx_convolve8_avg_horiz_neon,
+    vpx_convolve8_vert_neon, vpx_convolve8_avg_vert_neon,
+    vpx_convolve8_neon, vpx_convolve8_avg_neon,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+#endif  // HAVE_NEON_ASM
+
+const ConvolveParam kArrayConvolve8_neon[] = { ALL_SIZES(convolve8_neon) };
+INSTANTIATE_TEST_CASE_P(NEON, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve8_neon));
+#endif  // HAVE_NEON
+
+#if HAVE_DSPR2
+const ConvolveFunctions convolve8_dspr2(
+    vpx_convolve_copy_dspr2, vpx_convolve_avg_dspr2,
+    vpx_convolve8_horiz_dspr2, vpx_convolve8_avg_horiz_dspr2,
+    vpx_convolve8_vert_dspr2, vpx_convolve8_avg_vert_dspr2,
+    vpx_convolve8_dspr2, vpx_convolve8_avg_dspr2,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_dspr2[] = { ALL_SIZES(convolve8_dspr2) };
+INSTANTIATE_TEST_CASE_P(DSPR2, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve8_dspr2));
+#endif  // HAVE_DSPR2
+
+#if HAVE_MSA
+const ConvolveFunctions convolve8_msa(
+    vpx_convolve_copy_msa, vpx_convolve_avg_msa,
+    vpx_convolve8_horiz_msa, vpx_convolve8_avg_horiz_msa,
+    vpx_convolve8_vert_msa, vpx_convolve8_avg_vert_msa,
+    vpx_convolve8_msa, vpx_convolve8_avg_msa,
+    vpx_scaled_horiz_c, vpx_scaled_avg_horiz_c,
+    vpx_scaled_vert_c, vpx_scaled_avg_vert_c,
+    vpx_scaled_2d_c, vpx_scaled_avg_2d_c, 0);
+
+const ConvolveParam kArrayConvolve8_msa[] = { ALL_SIZES(convolve8_msa) };
+INSTANTIATE_TEST_CASE_P(MSA, ConvolveTest,
+                        ::testing::ValuesIn(kArrayConvolve8_msa));
+#endif  // HAVE_MSA
+}  // namespace
diff --git a/src/third_party/libvpx/test/cpu_speed_test.cc b/src/third_party/libvpx/test/cpu_speed_test.cc
new file mode 100644
index 0000000..572834c
--- /dev/null
+++ b/src/third_party/libvpx/test/cpu_speed_test.cc
@@ -0,0 +1,166 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+
+namespace {
+
+const int kMaxPSNR = 100;
+
+class CpuSpeedTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  CpuSpeedTest()
+      : EncoderTest(GET_PARAM(0)),
+        encoding_mode_(GET_PARAM(1)),
+        set_cpu_used_(GET_PARAM(2)),
+        min_psnr_(kMaxPSNR),
+        tune_content_(VP9E_CONTENT_DEFAULT) {}
+  virtual ~CpuSpeedTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+    if (encoding_mode_ != ::libvpx_test::kRealTime) {
+      cfg_.g_lag_in_frames = 25;
+      cfg_.rc_end_usage = VPX_VBR;
+    } else {
+      cfg_.g_lag_in_frames = 0;
+      cfg_.rc_end_usage = VPX_CBR;
+    }
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    min_psnr_ = kMaxPSNR;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+      encoder->Control(VP9E_SET_TUNE_CONTENT, tune_content_);
+      if (encoding_mode_ != ::libvpx_test::kRealTime) {
+        encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+        encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+        encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+        encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+      }
+    }
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.psnr.psnr[0] < min_psnr_)
+      min_psnr_ = pkt->data.psnr.psnr[0];
+  }
+
+  ::libvpx_test::TestMode encoding_mode_;
+  int set_cpu_used_;
+  double min_psnr_;
+  int tune_content_;
+};
+
+TEST_P(CpuSpeedTest, TestQ0) {
+  // Validate that this non multiple of 64 wide clip encodes and decodes
+  // without a mismatch when passing in a very low max q.  This pushes
+  // the encoder to producing lots of big partitions which will likely
+  // extend into the border and test the border condition.
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 400;
+  cfg_.rc_max_quantizer = 0;
+  cfg_.rc_min_quantizer = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       20);
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  EXPECT_GE(min_psnr_, kMaxPSNR);
+}
+
+TEST_P(CpuSpeedTest, TestScreencastQ0) {
+  ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25);
+  cfg_.g_timebase = video.timebase();
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 400;
+  cfg_.rc_max_quantizer = 0;
+  cfg_.rc_min_quantizer = 0;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  EXPECT_GE(min_psnr_, kMaxPSNR);
+}
+
+TEST_P(CpuSpeedTest, TestTuneScreen) {
+  ::libvpx_test::Y4mVideoSource video("screendata.y4m", 0, 25);
+  cfg_.g_timebase = video.timebase();
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_minsection_pct = 2000;
+  cfg_.rc_target_bitrate = 2000;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_min_quantizer = 0;
+  tune_content_ = VP9E_CONTENT_SCREEN;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(CpuSpeedTest, TestEncodeHighBitrate) {
+  // Validate that this non multiple of 64 wide clip encodes and decodes
+  // without a mismatch when passing in a very low max q.  This pushes
+  // the encoder to producing lots of big partitions which will likely
+  // extend into the border and test the border condition.
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 12000;
+  cfg_.rc_max_quantizer = 10;
+  cfg_.rc_min_quantizer = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       20);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(CpuSpeedTest, TestLowBitrate) {
+  // Validate that this clip encodes and decodes without a mismatch
+  // when passing in a very high min q.  This pushes the encoder to producing
+  // lots of small partitions which might will test the other condition.
+  cfg_.rc_2pass_vbr_minsection_pct = 5;
+  cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+  cfg_.rc_target_bitrate = 200;
+  cfg_.rc_min_quantizer = 40;
+
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       20);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP9_INSTANTIATE_TEST_CASE(
+    CpuSpeedTest,
+    ::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood,
+                      ::libvpx_test::kRealTime),
+    ::testing::Range(0, 9));
+
+VP10_INSTANTIATE_TEST_CASE(
+    CpuSpeedTest,
+    ::testing::Values(::libvpx_test::kTwoPassGood, ::libvpx_test::kOnePassGood),
+    ::testing::Range(0, 3));
+}  // namespace
diff --git a/src/third_party/libvpx/test/cq_test.cc b/src/third_party/libvpx/test/cq_test.cc
new file mode 100644
index 0000000..4e8019a
--- /dev/null
+++ b/src/third_party/libvpx/test/cq_test.cc
@@ -0,0 +1,134 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <cmath>
+#include <map>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+// CQ level range: [kCQLevelMin, kCQLevelMax).
+const int kCQLevelMin = 4;
+const int kCQLevelMax = 63;
+const int kCQLevelStep = 8;
+const unsigned int kCQTargetBitrate = 2000;
+
+class CQTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<int> {
+ public:
+  // maps the cqlevel to the bitrate produced.
+  typedef std::map<int, uint32_t> BitrateMap;
+
+  static void SetUpTestCase() {
+    bitrates_.clear();
+  }
+
+  static void TearDownTestCase() {
+    ASSERT_TRUE(!HasFailure())
+        << "skipping bitrate validation due to earlier failure.";
+    uint32_t prev_actual_bitrate = kCQTargetBitrate;
+    for (BitrateMap::const_iterator iter = bitrates_.begin();
+         iter != bitrates_.end(); ++iter) {
+      const uint32_t cq_actual_bitrate = iter->second;
+      EXPECT_LE(cq_actual_bitrate, prev_actual_bitrate)
+          << "cq_level: " << iter->first
+          << ", bitrate should decrease with increase in CQ level.";
+      prev_actual_bitrate = cq_actual_bitrate;
+    }
+  }
+
+ protected:
+  CQTest() : EncoderTest(GET_PARAM(0)), cq_level_(GET_PARAM(1)) {
+    init_flags_ = VPX_CODEC_USE_PSNR;
+  }
+
+  virtual ~CQTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(libvpx_test::kTwoPassGood);
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    file_size_ = 0;
+    psnr_ = 0.0;
+    n_frames_ = 0;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      if (cfg_.rc_end_usage == VPX_CQ) {
+        encoder->Control(VP8E_SET_CQ_LEVEL, cq_level_);
+      }
+      encoder->Control(VP8E_SET_CPUUSED, 3);
+    }
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    psnr_ += pow(10.0, pkt->data.psnr.psnr[0] / 10.0);
+    n_frames_++;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    file_size_ += pkt->data.frame.sz;
+  }
+
+  double GetLinearPSNROverBitrate() const {
+    double avg_psnr = log10(psnr_ / n_frames_) * 10.0;
+    return pow(10.0, avg_psnr / 10.0) / file_size_;
+  }
+
+  int cq_level() const { return cq_level_; }
+  size_t file_size() const { return file_size_; }
+  int n_frames() const { return n_frames_; }
+
+  static BitrateMap bitrates_;
+
+ private:
+  int cq_level_;
+  size_t file_size_;
+  double psnr_;
+  int n_frames_;
+};
+
+CQTest::BitrateMap CQTest::bitrates_;
+
+TEST_P(CQTest, LinearPSNRIsHigherForCQLevel) {
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = kCQTargetBitrate;
+  cfg_.g_lag_in_frames = 25;
+
+  cfg_.rc_end_usage = VPX_CQ;
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 30);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  const double cq_psnr_lin = GetLinearPSNROverBitrate();
+  const unsigned int cq_actual_bitrate =
+      static_cast<unsigned int>(file_size()) * 8 * 30 / (n_frames() * 1000);
+  EXPECT_LE(cq_actual_bitrate, kCQTargetBitrate);
+  bitrates_[cq_level()] = cq_actual_bitrate;
+
+  // try targeting the approximate same bitrate with VBR mode
+  cfg_.rc_end_usage = VPX_VBR;
+  cfg_.rc_target_bitrate = cq_actual_bitrate;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  const double vbr_psnr_lin = GetLinearPSNROverBitrate();
+  EXPECT_GE(cq_psnr_lin, vbr_psnr_lin);
+}
+
+VP8_INSTANTIATE_TEST_CASE(CQTest,
+                          ::testing::Range(kCQLevelMin, kCQLevelMax,
+                                           kCQLevelStep));
+}  // namespace
diff --git a/src/third_party/libvpx/test/datarate_test.cc b/src/third_party/libvpx/test/datarate_test.cc
new file mode 100644
index 0000000..2f1db9c
--- /dev/null
+++ b/src/third_party/libvpx/test/datarate_test.cc
@@ -0,0 +1,1156 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "./vpx_config.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx/vpx_codec.h"
+
+namespace {
+
+class DatarateTestLarge : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ public:
+  DatarateTestLarge() : EncoderTest(GET_PARAM(0)) {}
+
+  virtual ~DatarateTestLarge() {}
+
+ protected:
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    ResetModel();
+  }
+
+  virtual void ResetModel() {
+    last_pts_ = 0;
+    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
+    frame_number_ = 0;
+    first_drop_ = 0;
+    bits_total_ = 0;
+    duration_ = 0.0;
+    denoiser_offon_test_ = 0;
+    denoiser_offon_period_ = -1;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0)
+      encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
+
+    if (denoiser_offon_test_) {
+      ASSERT_GT(denoiser_offon_period_, 0)
+          << "denoiser_offon_period_ is not positive.";
+      if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
+        // Flip denoiser_on_ periodically
+        denoiser_on_ ^= 1;
+      }
+      encoder->Control(VP8E_SET_NOISE_SENSITIVITY, denoiser_on_);
+    }
+
+    const vpx_rational_t tb = video->timebase();
+    timebase_ = static_cast<double>(tb.num) / tb.den;
+    duration_ = 0;
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    // Time since last timestamp = duration.
+    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+
+    // TODO(jimbankoski): Remove these lines when the issue:
+    // http://code.google.com/p/webm/issues/detail?id=496 is fixed.
+    // For now the codec assumes buffer starts at starting buffer rate
+    // plus one frame's time.
+    if (last_pts_ == 0)
+      duration = 1;
+
+    // Add to the buffer the bits we'd expect from a constant bitrate server.
+    bits_in_buffer_model_ += static_cast<int64_t>(
+        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
+
+    /* Test the buffer model here before subtracting the frame. Do so because
+     * the way the leaky bucket model works in libvpx is to allow the buffer to
+     * empty - and then stop showing frames until we've got enough bits to
+     * show one. As noted in comment below (issue 495), this does not currently
+     * apply to key frames. For now exclude key frames in condition below. */
+    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
+                         ? true: false;
+    if (!key_frame) {
+      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
+          << pkt->data.frame.pts;
+    }
+
+    const int64_t frame_size_in_bits = pkt->data.frame.sz * 8;
+
+    // Subtract from the buffer the bits associated with a played back frame.
+    bits_in_buffer_model_ -= frame_size_in_bits;
+
+    // Update the running total of bits for end of test datarate checks.
+    bits_total_ += frame_size_in_bits;
+
+    // If first drop not set and we have a drop set it to this time.
+    if (!first_drop_ && duration > 1)
+      first_drop_ = last_pts_ + 1;
+
+    // Update the most recent pts.
+    last_pts_ = pkt->data.frame.pts;
+
+    // We update this so that we can calculate the datarate minus the last
+    // frame encoded in the file.
+    bits_in_last_frame_ = frame_size_in_bits;
+
+    ++frame_number_;
+  }
+
+  virtual void EndPassHook(void) {
+    if (bits_total_) {
+      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
+
+      duration_ = (last_pts_ + 1) * timebase_;
+
+      // Effective file datarate includes the time spent prebuffering.
+      effective_datarate_ = (bits_total_ - bits_in_last_frame_) / 1000.0
+          / (cfg_.rc_buf_initial_sz / 1000.0 + duration_);
+
+      file_datarate_ = file_size_in_kb / duration_;
+    }
+  }
+
+  vpx_codec_pts_t last_pts_;
+  int64_t bits_in_buffer_model_;
+  double timebase_;
+  int frame_number_;
+  vpx_codec_pts_t first_drop_;
+  int64_t bits_total_;
+  double duration_;
+  double file_datarate_;
+  double effective_datarate_;
+  size_t bits_in_last_frame_;
+  int denoiser_on_;
+  int denoiser_offon_test_;
+  int denoiser_offon_period_;
+};
+
+#if CONFIG_TEMPORAL_DENOISING
+// Check basic datarate targeting, for a single bitrate, but loop over the
+// various denoiser settings.
+TEST_P(DatarateTestLarge, DenoiserLevels) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+  for (int j = 1; j < 5; ++j) {
+    // Run over the denoiser levels.
+    // For the temporal denoiser (#if CONFIG_TEMPORAL_DENOISING) the level j
+    // refers to the 4 denoiser modes: denoiserYonly, denoiserOnYUV,
+    // denoiserOnAggressive, and denoiserOnAdaptive.
+    // For the spatial denoiser (if !CONFIG_TEMPORAL_DENOISING), the level j
+    // refers to the blur thresholds: 20, 40, 60 80.
+    // The j = 0 case (denoiser off) is covered in the tests below.
+    denoiser_on_ = j;
+    cfg_.rc_target_bitrate = 300;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+        << " The datarate for the file exceeds the target!";
+
+    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
+        << " The datarate for the file missed the target!";
+  }
+}
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is off
+// and on.
+TEST_P(DatarateTestLarge, DenoiserOffOn) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 299);
+  cfg_.rc_target_bitrate = 300;
+  ResetModel();
+  // The denoiser is off by default.
+  denoiser_on_ = 0;
+  // Set the offon test flag.
+  denoiser_offon_test_ = 1;
+  denoiser_offon_period_ = 100;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+      << " The datarate for the file exceeds the target!";
+  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
+      << " The datarate for the file missed the target!";
+}
+#endif  // CONFIG_TEMPORAL_DENOISING
+
+TEST_P(DatarateTestLarge, BasicBufferModel) {
+  denoiser_on_ = 0;
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  // 2 pass cbr datarate control has a bug hidden by the small # of
+  // frames selected in this encode. The problem is that even if the buffer is
+  // negative we produce a keyframe on a cutscene. Ignoring datarate
+  // constraints
+  // TODO(jimbankoski): ( Fix when issue
+  // http://code.google.com/p/webm/issues/detail?id=495 is addressed. )
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+
+  // There is an issue for low bitrates in real-time mode, where the
+  // effective_datarate slightly overshoots the target bitrate.
+  // This is same the issue as noted about (#495).
+  // TODO(jimbankoski/marpan): Update test to run for lower bitrates (< 100),
+  // when the issue is resolved.
+  for (int i = 100; i < 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, effective_datarate_ * 0.95)
+        << " The datarate for the file exceeds the target!";
+
+    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.3)
+        << " The datarate for the file missed the target!";
+  }
+}
+
+TEST_P(DatarateTestLarge, ChangingDropFrameThresh) {
+  denoiser_on_ = 0;
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_max_quantizer = 36;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.rc_target_bitrate = 200;
+  cfg_.kf_mode = VPX_KF_DISABLED;
+
+  const int frame_count = 40;
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, frame_count);
+
+  // Here we check that the first dropped frame gets earlier and earlier
+  // as the drop frame threshold is increased.
+
+  const int kDropFrameThreshTestStep = 30;
+  vpx_codec_pts_t last_drop = frame_count;
+  for (int i = 1; i < 91; i += kDropFrameThreshTestStep) {
+    cfg_.rc_dropframe_thresh = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_LE(first_drop_, last_drop)
+        << " The first dropped frame for drop_thresh " << i
+        << " > first dropped frame for drop_thresh "
+        << i - kDropFrameThreshTestStep;
+    last_drop = first_drop_;
+  }
+}
+
+class DatarateTestVP9Large : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ public:
+  DatarateTestVP9Large() : EncoderTest(GET_PARAM(0)) {}
+
+ protected:
+  virtual ~DatarateTestVP9Large() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    set_cpu_used_ = GET_PARAM(2);
+    ResetModel();
+  }
+
+  virtual void ResetModel() {
+    last_pts_ = 0;
+    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
+    frame_number_ = 0;
+    tot_frame_number_ = 0;
+    first_drop_ = 0;
+    num_drops_ = 0;
+    // Denoiser is off by default.
+    denoiser_on_ = 0;
+    // For testing up to 3 layers.
+    for (int i = 0; i < 3; ++i) {
+      bits_total_[i] = 0;
+    }
+    denoiser_offon_test_ = 0;
+    denoiser_offon_period_ = -1;
+  }
+
+  //
+  // Frame flags and layer id for temporal layers.
+  //
+
+  // For two layers, test pattern is:
+  //   1     3
+  // 0    2     .....
+  // For three layers, test pattern is:
+  //   1      3    5      7
+  //      2           6
+  // 0          4            ....
+  // LAST is always update on base/layer 0, GOLDEN is updated on layer 1.
+  // For this 3 layer example, the 2nd enhancement layer (layer 2) does not
+  // update any reference frames.
+  int SetFrameFlags(int frame_num, int num_temp_layers) {
+    int frame_flags = 0;
+    if (num_temp_layers == 2) {
+      if (frame_num % 2 == 0) {
+        // Layer 0: predict from L and ARF, update L.
+        frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
+                      VP8_EFLAG_NO_UPD_ARF;
+      } else {
+        // Layer 1: predict from L, G and ARF, and update G.
+        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+                      VP8_EFLAG_NO_UPD_ENTROPY;
+      }
+    } else if (num_temp_layers == 3) {
+      if (frame_num % 4 == 0) {
+        // Layer 0: predict from L and ARF; update L.
+        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                      VP8_EFLAG_NO_REF_GF;
+      } else if ((frame_num - 2) % 4 == 0) {
+        // Layer 1: predict from L, G, ARF; update G.
+        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST;
+      }  else if ((frame_num - 1) % 2 == 0) {
+        // Layer 2: predict from L, G, ARF; update none.
+        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                      VP8_EFLAG_NO_UPD_LAST;
+      }
+    }
+    return frame_flags;
+  }
+
+  int SetLayerId(int frame_num, int num_temp_layers) {
+    int layer_id = 0;
+    if (num_temp_layers == 2) {
+      if (frame_num % 2 == 0) {
+        layer_id = 0;
+      } else {
+        layer_id = 1;
+      }
+    } else if (num_temp_layers == 3) {
+      if (frame_num % 4 == 0) {
+        layer_id = 0;
+      } else if ((frame_num - 2) % 4 == 0) {
+        layer_id = 1;
+      } else if ((frame_num - 1) % 2 == 0) {
+        layer_id = 2;
+      }
+    }
+    return layer_id;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0)
+      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+
+    if (denoiser_offon_test_) {
+      ASSERT_GT(denoiser_offon_period_, 0)
+          << "denoiser_offon_period_ is not positive.";
+      if ((video->frame() + 1) % denoiser_offon_period_ == 0) {
+        // Flip denoiser_on_ periodically
+        denoiser_on_ ^= 1;
+      }
+    }
+
+    encoder->Control(VP9E_SET_NOISE_SENSITIVITY, denoiser_on_);
+
+    if (cfg_.ts_number_layers > 1) {
+      if (video->frame() == 0) {
+        encoder->Control(VP9E_SET_SVC, 1);
+      }
+      vpx_svc_layer_id_t layer_id;
+      layer_id.spatial_layer_id = 0;
+      frame_flags_ = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
+      layer_id.temporal_layer_id = SetLayerId(video->frame(),
+                                              cfg_.ts_number_layers);
+      encoder->Control(VP9E_SET_SVC_LAYER_ID, &layer_id);
+    }
+    const vpx_rational_t tb = video->timebase();
+    timebase_ = static_cast<double>(tb.num) / tb.den;
+    duration_ = 0;
+  }
+
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    // Time since last timestamp = duration.
+    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+
+    if (duration > 1) {
+      // If first drop not set and we have a drop set it to this time.
+      if (!first_drop_)
+        first_drop_ = last_pts_ + 1;
+      // Update the number of frame drops.
+      num_drops_ += static_cast<int>(duration - 1);
+      // Update counter for total number of frames (#frames input to encoder).
+      // Needed for setting the proper layer_id below.
+      tot_frame_number_ += static_cast<int>(duration - 1);
+    }
+
+    int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
+
+    // Add to the buffer the bits we'd expect from a constant bitrate server.
+    bits_in_buffer_model_ += static_cast<int64_t>(
+        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
+
+    // Buffer should not go negative.
+    ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
+        << pkt->data.frame.pts;
+
+    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+
+    // Update the total encoded bits. For temporal layers, update the cumulative
+    // encoded bits per layer.
+    for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
+      bits_total_[i] += frame_size_in_bits;
+    }
+
+    // Update the most recent pts.
+    last_pts_ = pkt->data.frame.pts;
+    ++frame_number_;
+    ++tot_frame_number_;
+  }
+
+  virtual void EndPassHook(void) {
+    for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
+        ++layer) {
+      duration_ = (last_pts_ + 1) * timebase_;
+      if (bits_total_[layer]) {
+        // Effective file datarate:
+        effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
+      }
+    }
+  }
+
+  vpx_codec_pts_t last_pts_;
+  double timebase_;
+  int frame_number_;      // Counter for number of non-dropped/encoded frames.
+  int tot_frame_number_;  // Counter for total number of input frames.
+  int64_t bits_total_[3];
+  double duration_;
+  double effective_datarate_[3];
+  int set_cpu_used_;
+  int64_t bits_in_buffer_model_;
+  vpx_codec_pts_t first_drop_;
+  int num_drops_;
+  int denoiser_on_;
+  int denoiser_offon_test_;
+  int denoiser_offon_period_;
+};
+
+// Check basic rate targeting for VBR mode.
+TEST_P(DatarateTestVP9Large, BasicRateTargetingVBR) {
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.g_error_resilient = 0;
+  cfg_.rc_end_usage = VPX_VBR;
+  cfg_.g_lag_in_frames = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 300);
+  for (int i = 400; i <= 800; i += 400) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.75)
+        << " The datarate for the file is lower than target by too much!";
+    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.25)
+        << " The datarate for the file is greater than target by too much!";
+  }
+}
+
+// Check basic rate targeting for CBR,
+TEST_P(DatarateTestVP9Large, BasicRateTargeting) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+  for (int i = 150; i < 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+        << " The datarate for the file is lower than target by too much!";
+    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+        << " The datarate for the file is greater than target by too much!";
+  }
+}
+
+// Check basic rate targeting for CBR.
+TEST_P(DatarateTestVP9Large, BasicRateTargeting444) {
+  ::libvpx_test::Y4mVideoSource video("rush_hour_444.y4m", 0, 140);
+
+  cfg_.g_profile = 1;
+  cfg_.g_timebase = video.timebase();
+
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+
+  for (int i = 250; i < 900; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(static_cast<double>(cfg_.rc_target_bitrate),
+              effective_datarate_[0] * 0.85)
+        << " The datarate for the file exceeds the target by too much!";
+    ASSERT_LE(static_cast<double>(cfg_.rc_target_bitrate),
+              effective_datarate_[0] * 1.15)
+        << " The datarate for the file missed the target!"
+        << cfg_.rc_target_bitrate << " "<< effective_datarate_;
+  }
+}
+
+// Check that (1) the first dropped frame gets earlier and earlier
+// as the drop frame threshold is increased, and (2) that the total number of
+// frame drops does not decrease as we increase frame drop threshold.
+// Use a lower qp-max to force some frame drops.
+TEST_P(DatarateTestVP9Large, ChangingDropFrameThresh) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_undershoot_pct = 20;
+  cfg_.rc_undershoot_pct = 20;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 50;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.rc_target_bitrate = 200;
+  cfg_.g_lag_in_frames = 0;
+  // TODO(marpan): Investigate datarate target failures with a smaller keyframe
+  // interval (128).
+  cfg_.kf_max_dist = 9999;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+
+  const int kDropFrameThreshTestStep = 30;
+  vpx_codec_pts_t last_drop = 140;
+  int last_num_drops = 0;
+  for (int i = 10; i < 100; i += kDropFrameThreshTestStep) {
+    cfg_.rc_dropframe_thresh = i;
+    ResetModel();
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+        << " The datarate for the file is lower than target by too much!";
+    ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+        << " The datarate for the file is greater than target by too much!";
+    ASSERT_LE(first_drop_, last_drop)
+        << " The first dropped frame for drop_thresh " << i
+        << " > first dropped frame for drop_thresh "
+        << i - kDropFrameThreshTestStep;
+    ASSERT_GE(num_drops_, last_num_drops * 0.85)
+        << " The number of dropped frames for drop_thresh " << i
+        << " < number of dropped frames for drop_thresh "
+        << i - kDropFrameThreshTestStep;
+    last_drop = first_drop_;
+    last_num_drops = num_drops_;
+  }
+}
+
+// Check basic rate targeting for 2 temporal layers.
+TEST_P(DatarateTestVP9Large, BasicRateTargeting2TemporalLayers) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  // 2 Temporal layers, no spatial layers: Framerate decimation (2, 1).
+  cfg_.ss_number_layers = 1;
+  cfg_.ts_number_layers = 2;
+  cfg_.ts_rate_decimator[0] = 2;
+  cfg_.ts_rate_decimator[1] = 1;
+
+  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+  if (deadline_ == VPX_DL_REALTIME)
+    cfg_.g_error_resilient = 1;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  for (int i = 200; i <= 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    // 60-40 bitrate allocation for 2 temporal layers.
+    cfg_.layer_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+    cfg_.layer_target_bitrate[1] = cfg_.rc_target_bitrate;
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
+          << " The datarate for the file is lower than target by too much, "
+              "for layer: " << j;
+      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
+          << " The datarate for the file is greater than target by too much, "
+              "for layer: " << j;
+    }
+  }
+}
+
+// Check basic rate targeting for 3 temporal layers.
+TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayers) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+  cfg_.ss_number_layers = 1;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+
+  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  for (int i = 200; i <= 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    // 40-20-40 bitrate allocation for 3 temporal layers.
+    cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+    cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+    cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+      // TODO(yaowu): Work out more stable rc control strategy and
+      //              Adjust the thresholds to be tighter than .75.
+      ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.75)
+          << " The datarate for the file is lower than target by too much, "
+              "for layer: " << j;
+      // TODO(yaowu): Work out more stable rc control strategy and
+      //              Adjust the thresholds to be tighter than 1.25.
+      ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.25)
+          << " The datarate for the file is greater than target by too much, "
+              "for layer: " << j;
+    }
+  }
+}
+
+// Check basic rate targeting for 3 temporal layers, with frame dropping.
+// Only for one (low) bitrate with lower max_quantizer, and somewhat higher
+// frame drop threshold, to force frame dropping.
+TEST_P(DatarateTestVP9Large, BasicRateTargeting3TemporalLayersFrameDropping) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  // Set frame drop threshold and rc_max_quantizer to force some frame drops.
+  cfg_.rc_dropframe_thresh = 20;
+  cfg_.rc_max_quantizer = 45;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  // 3 Temporal layers, no spatial layers: Framerate decimation (4, 2, 1).
+  cfg_.ss_number_layers = 1;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+
+  cfg_.temporal_layering_mode = VP9E_TEMPORAL_LAYERING_MODE_BYPASS;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  cfg_.rc_target_bitrate = 200;
+  ResetModel();
+  // 40-20-40 bitrate allocation for 3 temporal layers.
+  cfg_.layer_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+  cfg_.layer_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+  cfg_.layer_target_bitrate[2] = cfg_.rc_target_bitrate;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+    ASSERT_GE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 0.85)
+        << " The datarate for the file is lower than target by too much, "
+            "for layer: " << j;
+    ASSERT_LE(effective_datarate_[j], cfg_.layer_target_bitrate[j] * 1.15)
+        << " The datarate for the file is greater than target by too much, "
+            "for layer: " << j;
+    // Expect some frame drops in this test: for this 200 frames test,
+    // expect at least 10% and not more than 60% drops.
+    ASSERT_GE(num_drops_, 20);
+    ASSERT_LE(num_drops_, 130);
+  }
+}
+
+#if CONFIG_VP9_TEMPORAL_DENOISING
+// Check basic datarate targeting, for a single bitrate, when denoiser is on.
+TEST_P(DatarateTestVP9Large, DenoiserLevels) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 2;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 140);
+
+  // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+  // there is only one denoiser mode: denoiserYonly(which is 1),
+  // but may add more modes in the future.
+  cfg_.rc_target_bitrate = 300;
+  ResetModel();
+  // Turn on the denoiser.
+  denoiser_on_ = 1;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+      << " The datarate for the file is lower than target by too much!";
+  ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+      << " The datarate for the file is greater than target by too much!";
+}
+
+// Check basic datarate targeting, for a single bitrate, when denoiser is off
+// and on.
+TEST_P(DatarateTestVP9Large, DenoiserOffOn) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 2;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 299);
+
+  // For the temporal denoiser (#if CONFIG_VP9_TEMPORAL_DENOISING),
+  // there is only one denoiser mode: denoiserYonly(which is 1),
+  // but may add more modes in the future.
+  cfg_.rc_target_bitrate = 300;
+  ResetModel();
+  // The denoiser is off by default.
+  denoiser_on_ = 0;
+  // Set the offon test flag.
+  denoiser_offon_test_ = 1;
+  denoiser_offon_period_ = 100;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(effective_datarate_[0], cfg_.rc_target_bitrate * 0.85)
+      << " The datarate for the file is lower than target by too much!";
+  ASSERT_LE(effective_datarate_[0], cfg_.rc_target_bitrate * 1.15)
+      << " The datarate for the file is greater than target by too much!";
+}
+#endif  // CONFIG_VP9_TEMPORAL_DENOISING
+
+class DatarateOnePassCbrSvc : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ public:
+  DatarateOnePassCbrSvc() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~DatarateOnePassCbrSvc() {}
+ protected:
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    speed_setting_ = GET_PARAM(2);
+    ResetModel();
+  }
+  virtual void ResetModel() {
+    last_pts_ = 0;
+    bits_in_buffer_model_ = cfg_.rc_target_bitrate * cfg_.rc_buf_initial_sz;
+    frame_number_ = 0;
+    first_drop_ = 0;
+    bits_total_ = 0;
+    duration_ = 0.0;
+    mismatch_psnr_ = 0.0;
+    mismatch_nframes_ = 0;
+  }
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+  }
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      int i;
+      for (i = 0; i < VPX_MAX_LAYERS; ++i) {
+        svc_params_.max_quantizers[i] = 63;
+        svc_params_.min_quantizers[i] = 0;
+      }
+      encoder->Control(VP9E_SET_SVC, 1);
+      encoder->Control(VP9E_SET_SVC_PARAMETERS, &svc_params_);
+      encoder->Control(VP8E_SET_CPUUSED, speed_setting_);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, 0);
+      encoder->Control(VP8E_SET_MAX_INTRA_BITRATE_PCT, 300);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, (cfg_.g_threads >> 1));
+    }
+    const vpx_rational_t tb = video->timebase();
+    timebase_ = static_cast<double>(tb.num) / tb.den;
+    duration_ = 0;
+  }
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+    if (last_pts_ == 0)
+      duration = 1;
+    bits_in_buffer_model_ += static_cast<int64_t>(
+        duration * timebase_ * cfg_.rc_target_bitrate * 1000);
+    const bool key_frame = (pkt->data.frame.flags & VPX_FRAME_IS_KEY)
+                         ? true: false;
+    if (!key_frame) {
+      ASSERT_GE(bits_in_buffer_model_, 0) << "Buffer Underrun at frame "
+          << pkt->data.frame.pts;
+    }
+    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+    bits_in_buffer_model_ -= frame_size_in_bits;
+    bits_total_ += frame_size_in_bits;
+    if (!first_drop_ && duration > 1)
+      first_drop_ = last_pts_ + 1;
+    last_pts_ = pkt->data.frame.pts;
+    bits_in_last_frame_ = frame_size_in_bits;
+    ++frame_number_;
+  }
+  virtual void EndPassHook(void) {
+    if (bits_total_) {
+      const double file_size_in_kb = bits_total_ / 1000.;  // bits per kilobit
+      duration_ = (last_pts_ + 1) * timebase_;
+      file_datarate_ = file_size_in_kb / duration_;
+    }
+  }
+
+  virtual void MismatchHook(const vpx_image_t *img1,
+                            const vpx_image_t *img2) {
+    double mismatch_psnr = compute_psnr(img1, img2);
+    mismatch_psnr_ += mismatch_psnr;
+    ++mismatch_nframes_;
+  }
+
+  unsigned int GetMismatchFrames() {
+    return mismatch_nframes_;
+  }
+
+  vpx_codec_pts_t last_pts_;
+  int64_t bits_in_buffer_model_;
+  double timebase_;
+  int frame_number_;
+  vpx_codec_pts_t first_drop_;
+  int64_t bits_total_;
+  double duration_;
+  double file_datarate_;
+  size_t bits_in_last_frame_;
+  vpx_svc_extra_cfg_t svc_params_;
+  int speed_setting_;
+  double mismatch_psnr_;
+  int mismatch_nframes_;
+};
+static void assign_layer_bitrates(vpx_codec_enc_cfg_t *const enc_cfg,
+    const vpx_svc_extra_cfg_t *svc_params,
+    int spatial_layers,
+    int temporal_layers,
+    int temporal_layering_mode) {
+  int sl, spatial_layer_target;
+  float total = 0;
+  float alloc_ratio[VPX_MAX_LAYERS] = {0};
+  for (sl = 0; sl < spatial_layers; ++sl) {
+    if (svc_params->scaling_factor_den[sl] > 0) {
+      alloc_ratio[sl] = (float)(svc_params->scaling_factor_num[sl] *
+          1.0 / svc_params->scaling_factor_den[sl]);
+      total += alloc_ratio[sl];
+    }
+  }
+  for (sl = 0; sl < spatial_layers; ++sl) {
+    enc_cfg->ss_target_bitrate[sl] = spatial_layer_target =
+        (unsigned int)(enc_cfg->rc_target_bitrate *
+            alloc_ratio[sl] / total);
+    const int index = sl * temporal_layers;
+    if (temporal_layering_mode == 3) {
+      enc_cfg->layer_target_bitrate[index] =
+          spatial_layer_target >> 1;
+      enc_cfg->layer_target_bitrate[index + 1] =
+          (spatial_layer_target >> 1) + (spatial_layer_target >> 2);
+      enc_cfg->layer_target_bitrate[index + 2] =
+          spatial_layer_target;
+    } else if (temporal_layering_mode == 2) {
+      enc_cfg->layer_target_bitrate[index] =
+          spatial_layer_target * 2 / 3;
+      enc_cfg->layer_target_bitrate[index + 1] =
+          spatial_layer_target;
+    }
+  }
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Run CIF clip with 1 thread.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 2;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 1;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 144;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 288;
+  svc_params_.scaling_factor_den[1] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.kf_max_dist = 9999;
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  // TODO(wonkap/marpan): Check that effective_datarate for each layer hits the
+  // layer target_bitrate.
+  for (int i = 200; i <= 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    ResetModel();
+    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+        cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+            << " The datarate for the file exceeds the target by too much!";
+    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
+        << " The datarate for the file is lower than the target by too much!";
+    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+  }
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and 3
+// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayersSmallKf) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 2;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 1;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 144;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 288;
+  svc_params_.scaling_factor_den[1] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  cfg_.rc_target_bitrate = 400;
+  // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
+  // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
+  for (int j = 64; j <= 67; j++) {
+    cfg_.kf_max_dist = j;
+    ResetModel();
+    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+        cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+            << " The datarate for the file exceeds the target by too much!";
+    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
+        << " The datarate for the file is lower than the target by too much!";
+    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+  }
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 2 spatial layers and
+// 3 temporal layers. Run HD clip with 4 threads.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc2SpatialLayers4threads) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 2;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 4;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 144;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 288;
+  svc_params_.scaling_factor_den[1] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.kf_max_dist = 9999;
+  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
+                                       30, 1, 0, 300);
+  cfg_.rc_target_bitrate = 800;
+  ResetModel();
+  assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+      cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+          << " The datarate for the file exceeds the target by too much!";
+  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.15)
+      << " The datarate for the file is lower than the target by too much!";
+  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Run CIF clip with 1 thread.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 3;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 1;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 72;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 144;
+  svc_params_.scaling_factor_den[1] = 288;
+  svc_params_.scaling_factor_num[2] = 288;
+  svc_params_.scaling_factor_den[2] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.kf_max_dist = 9999;
+  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
+                                       30, 1, 0, 300);
+  cfg_.rc_target_bitrate = 800;
+  ResetModel();
+  assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+     cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+          << " The datarate for the file exceeds the target by too much!";
+  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
+      << " The datarate for the file is lower than the target by too much!";
+  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and 3
+// temporal layers. Run CIF clip with 1 thread, and few short key frame periods.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayersSmallKf) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 3;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 1;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 72;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 144;
+  svc_params_.scaling_factor_den[1] = 288;
+  svc_params_.scaling_factor_num[2] = 288;
+  svc_params_.scaling_factor_den[2] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
+                                       30, 1, 0, 300);
+  cfg_.rc_target_bitrate = 800;
+  // For this 3 temporal layer case, pattern repeats every 4 frames, so choose
+  // 4 key neighboring key frame periods (so key frame will land on 0-2-1-2).
+  for (int j = 32; j <= 35; j++) {
+    cfg_.kf_max_dist = j;
+    ResetModel();
+    assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+       cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+            << " The datarate for the file exceeds the target by too much!";
+    ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.30)
+        << " The datarate for the file is lower than the target by too much!";
+    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+  }
+}
+
+// Check basic rate targeting for 1 pass CBR SVC: 3 spatial layers and
+// 3 temporal layers. Run HD clip with 4 threads.
+TEST_P(DatarateOnePassCbrSvc, OnePassCbrSvc3SpatialLayers4threads) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_min_quantizer = 0;
+  cfg_.rc_max_quantizer = 63;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.ss_number_layers = 3;
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.g_error_resilient = 1;
+  cfg_.g_threads = 4;
+  cfg_.temporal_layering_mode = 3;
+  svc_params_.scaling_factor_num[0] = 72;
+  svc_params_.scaling_factor_den[0] = 288;
+  svc_params_.scaling_factor_num[1] = 144;
+  svc_params_.scaling_factor_den[1] = 288;
+  svc_params_.scaling_factor_num[2] = 288;
+  svc_params_.scaling_factor_den[2] = 288;
+  cfg_.rc_dropframe_thresh = 10;
+  cfg_.kf_max_dist = 9999;
+  ::libvpx_test::I420VideoSource video("niklas_1280_720_30.y4m", 1280, 720,
+                                       30, 1, 0, 300);
+  cfg_.rc_target_bitrate = 800;
+  ResetModel();
+  assign_layer_bitrates(&cfg_, &svc_params_, cfg_.ss_number_layers,
+      cfg_.ts_number_layers, cfg_.temporal_layering_mode);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_GE(cfg_.rc_target_bitrate, file_datarate_ * 0.85)
+          << " The datarate for the file exceeds the target by too much!";
+  ASSERT_LE(cfg_.rc_target_bitrate, file_datarate_ * 1.22)
+      << " The datarate for the file is lower than the target by too much!";
+  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+}
+
+VP8_INSTANTIATE_TEST_CASE(DatarateTestLarge, ALL_TEST_MODES);
+VP9_INSTANTIATE_TEST_CASE(DatarateTestVP9Large,
+                          ::testing::Values(::libvpx_test::kOnePassGood,
+                                            ::libvpx_test::kRealTime),
+                          ::testing::Range(2, 9));
+VP9_INSTANTIATE_TEST_CASE(DatarateOnePassCbrSvc,
+                          ::testing::Values(::libvpx_test::kRealTime),
+                          ::testing::Range(5, 9));
+}  // namespace
diff --git a/src/third_party/libvpx/test/dct16x16_test.cc b/src/third_party/libvpx/test/dct16x16_test.cc
new file mode 100644
index 0000000..ddaf939
--- /dev/null
+++ b/src/third_party/libvpx/test/dct16x16_test.cc
@@ -0,0 +1,994 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+#ifdef _MSC_VER
+static int round(double x) {
+  if (x < 0)
+    return static_cast<int>(ceil(x - 0.5));
+  else
+    return static_cast<int>(floor(x + 0.5));
+}
+#endif
+
+const int kNumCoeffs = 256;
+const double C1 = 0.995184726672197;
+const double C2 = 0.98078528040323;
+const double C3 = 0.956940335732209;
+const double C4 = 0.923879532511287;
+const double C5 = 0.881921264348355;
+const double C6 = 0.831469612302545;
+const double C7 = 0.773010453362737;
+const double C8 = 0.707106781186548;
+const double C9 = 0.634393284163646;
+const double C10 = 0.555570233019602;
+const double C11 = 0.471396736825998;
+const double C12 = 0.38268343236509;
+const double C13 = 0.290284677254462;
+const double C14 = 0.195090322016128;
+const double C15 = 0.098017140329561;
+
+void butterfly_16x16_dct_1d(double input[16], double output[16]) {
+  double step[16];
+  double intermediate[16];
+  double temp1, temp2;
+
+  // step 1
+  step[ 0] = input[0] + input[15];
+  step[ 1] = input[1] + input[14];
+  step[ 2] = input[2] + input[13];
+  step[ 3] = input[3] + input[12];
+  step[ 4] = input[4] + input[11];
+  step[ 5] = input[5] + input[10];
+  step[ 6] = input[6] + input[ 9];
+  step[ 7] = input[7] + input[ 8];
+  step[ 8] = input[7] - input[ 8];
+  step[ 9] = input[6] - input[ 9];
+  step[10] = input[5] - input[10];
+  step[11] = input[4] - input[11];
+  step[12] = input[3] - input[12];
+  step[13] = input[2] - input[13];
+  step[14] = input[1] - input[14];
+  step[15] = input[0] - input[15];
+
+  // step 2
+  output[0] = step[0] + step[7];
+  output[1] = step[1] + step[6];
+  output[2] = step[2] + step[5];
+  output[3] = step[3] + step[4];
+  output[4] = step[3] - step[4];
+  output[5] = step[2] - step[5];
+  output[6] = step[1] - step[6];
+  output[7] = step[0] - step[7];
+
+  temp1 = step[ 8] * C7;
+  temp2 = step[15] * C9;
+  output[ 8] = temp1 + temp2;
+
+  temp1 = step[ 9] * C11;
+  temp2 = step[14] * C5;
+  output[ 9] = temp1 - temp2;
+
+  temp1 = step[10] * C3;
+  temp2 = step[13] * C13;
+  output[10] = temp1 + temp2;
+
+  temp1 = step[11] * C15;
+  temp2 = step[12] * C1;
+  output[11] = temp1 - temp2;
+
+  temp1 = step[11] * C1;
+  temp2 = step[12] * C15;
+  output[12] = temp2 + temp1;
+
+  temp1 = step[10] * C13;
+  temp2 = step[13] * C3;
+  output[13] = temp2 - temp1;
+
+  temp1 = step[ 9] * C5;
+  temp2 = step[14] * C11;
+  output[14] = temp2 + temp1;
+
+  temp1 = step[ 8] * C9;
+  temp2 = step[15] * C7;
+  output[15] = temp2 - temp1;
+
+  // step 3
+  step[ 0] = output[0] + output[3];
+  step[ 1] = output[1] + output[2];
+  step[ 2] = output[1] - output[2];
+  step[ 3] = output[0] - output[3];
+
+  temp1 = output[4] * C14;
+  temp2 = output[7] * C2;
+  step[ 4] = temp1 + temp2;
+
+  temp1 = output[5] * C10;
+  temp2 = output[6] * C6;
+  step[ 5] = temp1 + temp2;
+
+  temp1 = output[5] * C6;
+  temp2 = output[6] * C10;
+  step[ 6] = temp2 - temp1;
+
+  temp1 = output[4] * C2;
+  temp2 = output[7] * C14;
+  step[ 7] = temp2 - temp1;
+
+  step[ 8] = output[ 8] + output[11];
+  step[ 9] = output[ 9] + output[10];
+  step[10] = output[ 9] - output[10];
+  step[11] = output[ 8] - output[11];
+
+  step[12] = output[12] + output[15];
+  step[13] = output[13] + output[14];
+  step[14] = output[13] - output[14];
+  step[15] = output[12] - output[15];
+
+  // step 4
+  output[ 0] = (step[ 0] + step[ 1]);
+  output[ 8] = (step[ 0] - step[ 1]);
+
+  temp1 = step[2] * C12;
+  temp2 = step[3] * C4;
+  temp1 = temp1 + temp2;
+  output[ 4] = 2*(temp1 * C8);
+
+  temp1 = step[2] * C4;
+  temp2 = step[3] * C12;
+  temp1 = temp2 - temp1;
+  output[12] = 2 * (temp1 * C8);
+
+  output[ 2] = 2 * ((step[4] + step[ 5]) * C8);
+  output[14] = 2 * ((step[7] - step[ 6]) * C8);
+
+  temp1 = step[4] - step[5];
+  temp2 = step[6] + step[7];
+  output[ 6] = (temp1 + temp2);
+  output[10] = (temp1 - temp2);
+
+  intermediate[8] = step[8] + step[14];
+  intermediate[9] = step[9] + step[15];
+
+  temp1 = intermediate[8] * C12;
+  temp2 = intermediate[9] * C4;
+  temp1 = temp1 - temp2;
+  output[3] = 2 * (temp1 * C8);
+
+  temp1 = intermediate[8] * C4;
+  temp2 = intermediate[9] * C12;
+  temp1 = temp2 + temp1;
+  output[13] = 2 * (temp1 * C8);
+
+  output[ 9] = 2 * ((step[10] + step[11]) * C8);
+
+  intermediate[11] = step[10] - step[11];
+  intermediate[12] = step[12] + step[13];
+  intermediate[13] = step[12] - step[13];
+  intermediate[14] = step[ 8] - step[14];
+  intermediate[15] = step[ 9] - step[15];
+
+  output[15] = (intermediate[11] + intermediate[12]);
+  output[ 1] = -(intermediate[11] - intermediate[12]);
+
+  output[ 7] = 2 * (intermediate[13] * C8);
+
+  temp1 = intermediate[14] * C12;
+  temp2 = intermediate[15] * C4;
+  temp1 = temp1 - temp2;
+  output[11] = -2 * (temp1 * C8);
+
+  temp1 = intermediate[14] * C4;
+  temp2 = intermediate[15] * C12;
+  temp1 = temp2 + temp1;
+  output[ 5] = 2 * (temp1 * C8);
+}
+
+void reference_16x16_dct_2d(int16_t input[256], double output[256]) {
+  // First transform columns
+  for (int i = 0; i < 16; ++i) {
+    double temp_in[16], temp_out[16];
+    for (int j = 0; j < 16; ++j)
+      temp_in[j] = input[j * 16 + i];
+    butterfly_16x16_dct_1d(temp_in, temp_out);
+    for (int j = 0; j < 16; ++j)
+      output[j * 16 + i] = temp_out[j];
+  }
+  // Then transform rows
+  for (int i = 0; i < 16; ++i) {
+    double temp_in[16], temp_out[16];
+    for (int j = 0; j < 16; ++j)
+      temp_in[j] = output[j + i * 16];
+    butterfly_16x16_dct_1d(temp_in, temp_out);
+    // Scale by some magic number
+    for (int j = 0; j < 16; ++j)
+      output[j + i * 16] = temp_out[j]/2;
+  }
+}
+
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+                        int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+                        int tx_type);
+
+typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct16x16Param;
+typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht16x16Param;
+typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t>
+    Idct16x16Param;
+
+void fdct16x16_ref(const int16_t *in, tran_low_t *out, int stride,
+                   int /*tx_type*/) {
+  vpx_fdct16x16_c(in, out, stride);
+}
+
+void idct16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
+                   int /*tx_type*/) {
+  vpx_idct16x16_256_add_c(in, dest, stride);
+}
+
+void fht16x16_ref(const int16_t *in, tran_low_t *out, int stride,
+                  int tx_type) {
+  vp9_fht16x16_c(in, out, stride, tx_type);
+}
+
+void iht16x16_ref(const tran_low_t *in, uint8_t *dest, int stride,
+                  int tx_type) {
+  vp9_iht16x16_256_add_c(in, dest, stride, tx_type);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct16x16_10(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_256_add_c(in, out, stride, 10);
+}
+
+void idct16x16_12(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_256_add_c(in, out, stride, 12);
+}
+
+void idct16x16_10_ref(const tran_low_t *in, uint8_t *out, int stride,
+                      int /*tx_type*/) {
+  idct16x16_10(in, out, stride);
+}
+
+void idct16x16_12_ref(const tran_low_t *in, uint8_t *out, int stride,
+                      int /*tx_type*/) {
+  idct16x16_12(in, out, stride);
+}
+
+void iht16x16_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 10);
+}
+
+void iht16x16_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht16x16_256_add_c(in, out, stride, tx_type, 12);
+}
+
+#if HAVE_SSE2
+void idct16x16_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_10_add_c(in, out, stride, 10);
+}
+
+void idct16x16_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_10_add_c(in, out, stride, 12);
+}
+
+void idct16x16_256_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 10);
+}
+
+void idct16x16_256_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_256_add_sse2(in, out, stride, 12);
+}
+
+void idct16x16_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 10);
+}
+
+void idct16x16_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct16x16_10_add_sse2(in, out, stride, 12);
+}
+#endif  // HAVE_SSE2
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+class Trans16x16TestBase {
+ public:
+  virtual ~Trans16x16TestBase() {}
+
+ protected:
+  virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
+
+  virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
+
+  void RunAccuracyCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    uint32_t max_error = 0;
+    int64_t total_error = 0;
+    const int count_test_block = 10000;
+    for (int i = 0; i < count_test_block; ++i) {
+      DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
+      DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+      DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8();
+          dst[j] = rnd.Rand8();
+          test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand16() & mask_;
+          dst16[j] = rnd.Rand16() & mask_;
+          test_input_block[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
+                                          test_temp_block, pitch_));
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
+#endif
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int32_t diff =
+            bit_depth_ == VPX_BITS_8 ?  dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const int32_t diff = dst[j] - src[j];
+#endif
+        const uint32_t error = diff * diff;
+        if (max_error < error)
+          max_error = error;
+        total_error += error;
+      }
+    }
+
+    EXPECT_GE(1u  << 2 * (bit_depth_ - 8), max_error)
+        << "Error: 16x16 FHT/IHT has an individual round trip error > 1";
+
+    EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
+        << "Error: 16x16 FHT/IHT has average round trip error > 1 per block";
+  }
+
+  void RunCoeffCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j)
+        input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+
+      fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
+
+      // The minimum quant value is 4.
+      for (int j = 0; j < kNumCoeffs; ++j)
+        EXPECT_EQ(output_block[j], output_ref_block[j]);
+    }
+  }
+
+  void RunMemCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
+      }
+      if (i == 0) {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = mask_;
+      } else if (i == 1) {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = -mask_;
+      }
+
+      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
+                                          output_block, pitch_));
+
+      // The minimum quant value is 4.
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        EXPECT_EQ(output_block[j], output_ref_block[j]);
+        EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
+            << "Error: 16x16 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
+      }
+    }
+  }
+
+  void RunQuantCheck(int dc_thred, int ac_thred) {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 100000;
+    DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
+      }
+      if (i == 0)
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = mask_;
+      if (i == 1)
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = -mask_;
+
+      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
+
+      // clear reconstructed pixel buffers
+      memset(dst, 0, kNumCoeffs * sizeof(uint8_t));
+      memset(ref, 0, kNumCoeffs * sizeof(uint8_t));
+#if CONFIG_VP9_HIGHBITDEPTH
+      memset(dst16, 0, kNumCoeffs * sizeof(uint16_t));
+      memset(ref16, 0, kNumCoeffs * sizeof(uint16_t));
+#endif
+
+      // quantization with maximum allowed step sizes
+      output_ref_block[0] = (output_ref_block[0] / dc_thred) * dc_thred;
+      for (int j = 1; j < kNumCoeffs; ++j)
+        output_ref_block[j] = (output_ref_block[j] / ac_thred) * ac_thred;
+      if (bit_depth_ == VPX_BITS_8) {
+        inv_txfm_ref(output_ref_block, ref, pitch_, tx_type_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        inv_txfm_ref(output_ref_block, CONVERT_TO_BYTEPTR(ref16), pitch_,
+                     tx_type_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(output_ref_block,
+                                            CONVERT_TO_BYTEPTR(dst16), pitch_));
+#endif
+      }
+      if (bit_depth_ == VPX_BITS_8) {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          EXPECT_EQ(ref[j], dst[j]);
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          EXPECT_EQ(ref16[j], dst16[j]);
+#endif
+      }
+    }
+  }
+
+  void RunInvAccuracyCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+    for (int i = 0; i < count_test_block; ++i) {
+      double out_r[kNumCoeffs];
+
+      // Initialize a test block with input range [-255, 255].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8();
+          dst[j] = rnd.Rand8();
+          in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand16() & mask_;
+          dst16[j] = rnd.Rand16() & mask_;
+          in[j] = src16[j] - dst16[j];
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+
+      reference_16x16_dct_2d(in, out_r);
+      for (int j = 0; j < kNumCoeffs; ++j)
+        coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, 16));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
+                                            16));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const uint32_t diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const uint32_t diff = dst[j] - src[j];
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        const uint32_t error = diff * diff;
+        EXPECT_GE(1u, error)
+            << "Error: 16x16 IDCT has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+
+  void CompareInvReference(IdctFunc ref_txfm, int thresh) {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 10000;
+    const int eob = 10;
+    const int16_t *scan = vp9_default_scan_orders[TX_16X16].scan;
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+    for (int i = 0; i < count_test_block; ++i) {
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (j < eob) {
+          // Random values less than the threshold, either positive or negative
+          coeff[scan[j]] = rnd(thresh) * (1 - 2 * (i % 2));
+        } else {
+          coeff[scan[j]] = 0;
+        }
+        if (bit_depth_ == VPX_BITS_8) {
+          dst[j] = 0;
+          ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          dst16[j] = 0;
+          ref16[j] = 0;
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+      if (bit_depth_ == VPX_BITS_8) {
+        ref_txfm(coeff, ref, pitch_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+      } else {
+#if CONFIG_VP9_HIGHBITDEPTH
+        ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
+                                 pitch_));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const uint32_t diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
+#else
+        const uint32_t diff = dst[j] - ref[j];
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        const uint32_t error = diff * diff;
+        EXPECT_EQ(0u, error)
+            << "Error: 16x16 IDCT Comparison has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+
+  int pitch_;
+  int tx_type_;
+  vpx_bit_depth_t bit_depth_;
+  int mask_;
+  FhtFunc fwd_txfm_ref;
+  IhtFunc inv_txfm_ref;
+};
+
+class Trans16x16DCT
+    : public Trans16x16TestBase,
+      public ::testing::TestWithParam<Dct16x16Param> {
+ public:
+  virtual ~Trans16x16DCT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    bit_depth_ = GET_PARAM(3);
+    pitch_    = 16;
+    fwd_txfm_ref = fdct16x16_ref;
+    inv_txfm_ref = idct16x16_ref;
+    mask_ = (1 << bit_depth_) - 1;
+#if CONFIG_VP9_HIGHBITDEPTH
+    switch (bit_depth_) {
+      case VPX_BITS_10:
+        inv_txfm_ref = idct16x16_10_ref;
+        break;
+      case VPX_BITS_12:
+        inv_txfm_ref = idct16x16_12_ref;
+        break;
+      default:
+        inv_txfm_ref = idct16x16_ref;
+        break;
+    }
+#else
+    inv_txfm_ref = idct16x16_ref;
+#endif
+  }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride);
+  }
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+
+  FdctFunc fwd_txfm_;
+  IdctFunc inv_txfm_;
+};
+
+TEST_P(Trans16x16DCT, AccuracyCheck) {
+  RunAccuracyCheck();
+}
+
+TEST_P(Trans16x16DCT, CoeffCheck) {
+  RunCoeffCheck();
+}
+
+TEST_P(Trans16x16DCT, MemCheck) {
+  RunMemCheck();
+}
+
+TEST_P(Trans16x16DCT, QuantCheck) {
+  // Use maximally allowed quantization step sizes for DC and AC
+  // coefficients respectively.
+  RunQuantCheck(1336, 1828);
+}
+
+TEST_P(Trans16x16DCT, InvAccuracyCheck) {
+  RunInvAccuracyCheck();
+}
+
+class Trans16x16HT
+    : public Trans16x16TestBase,
+      public ::testing::TestWithParam<Ht16x16Param> {
+ public:
+  virtual ~Trans16x16HT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    bit_depth_ = GET_PARAM(3);
+    pitch_    = 16;
+    fwd_txfm_ref = fht16x16_ref;
+    inv_txfm_ref = iht16x16_ref;
+    mask_ = (1 << bit_depth_) - 1;
+#if CONFIG_VP9_HIGHBITDEPTH
+    switch (bit_depth_) {
+      case VPX_BITS_10:
+        inv_txfm_ref = iht16x16_10;
+        break;
+      case VPX_BITS_12:
+        inv_txfm_ref = iht16x16_12;
+        break;
+      default:
+        inv_txfm_ref = iht16x16_ref;
+        break;
+    }
+#else
+    inv_txfm_ref = iht16x16_ref;
+#endif
+  }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride, tx_type_);
+  }
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride, tx_type_);
+  }
+
+  FhtFunc fwd_txfm_;
+  IhtFunc inv_txfm_;
+};
+
+TEST_P(Trans16x16HT, AccuracyCheck) {
+  RunAccuracyCheck();
+}
+
+TEST_P(Trans16x16HT, CoeffCheck) {
+  RunCoeffCheck();
+}
+
+TEST_P(Trans16x16HT, MemCheck) {
+  RunMemCheck();
+}
+
+TEST_P(Trans16x16HT, QuantCheck) {
+  // The encoder skips any non-DC intra prediction modes,
+  // when the quantization step size goes beyond 988.
+  RunQuantCheck(429, 729);
+}
+
+class InvTrans16x16DCT
+    : public Trans16x16TestBase,
+      public ::testing::TestWithParam<Idct16x16Param> {
+ public:
+  virtual ~InvTrans16x16DCT() {}
+
+  virtual void SetUp() {
+    ref_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    thresh_ = GET_PARAM(2);
+    bit_depth_ = GET_PARAM(3);
+    pitch_ = 16;
+    mask_ = (1 << bit_depth_) - 1;
+}
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(int16_t * /*in*/, tran_low_t * /*out*/, int /*stride*/) {}
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+
+  IdctFunc ref_txfm_;
+  IdctFunc inv_txfm_;
+  int thresh_;
+};
+
+TEST_P(InvTrans16x16DCT, CompareReference) {
+  CompareInvReference(ref_txfm_, thresh_);
+}
+
+class PartialTrans16x16Test
+    : public ::testing::TestWithParam<
+          std::tr1::tuple<FdctFunc, vpx_bit_depth_t> > {
+ public:
+  virtual ~PartialTrans16x16Test() {}
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    bit_depth_ = GET_PARAM(1);
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  vpx_bit_depth_t bit_depth_;
+  FdctFunc fwd_txfm_;
+};
+
+TEST_P(PartialTrans16x16Test, Extremes) {
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int16_t maxval =
+      static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
+#else
+  const int16_t maxval = 255;
+#endif
+  const int minval = -maxval;
+  DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
+
+  for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
+  EXPECT_EQ((maxval * kNumCoeffs) >> 1, output[0]);
+
+  for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
+  EXPECT_EQ((minval * kNumCoeffs) >> 1, output[0]);
+}
+
+TEST_P(PartialTrans16x16Test, Random) {
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int16_t maxval =
+      static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
+#else
+  const int16_t maxval = 255;
+#endif
+  DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+  int sum = 0;
+  for (int i = 0; i < kNumCoeffs; ++i) {
+    const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
+    input[i] = val;
+    sum += val;
+  }
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 16));
+  EXPECT_EQ(sum >> 1, output[0]);
+}
+
+using std::tr1::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct16x16_c, &idct16x16_12, 0, VPX_BITS_12),
+        make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct16x16_c, &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans16x16HT,
+    ::testing::Values(
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 0, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 1, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 2, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_10, 3, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 0, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 1, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 2, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht16x16_c, &iht16x16_12, 3, VPX_BITS_12),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    C, PartialTrans16x16Test,
+    ::testing::Values(make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_8),
+                      make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_10),
+                      make_tuple(&vpx_highbd_fdct16x16_1_c, VPX_BITS_12)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans16x16HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_c, &vp9_iht16x16_256_add_c, 3, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(C, PartialTrans16x16Test,
+                        ::testing::Values(make_tuple(&vpx_fdct16x16_1_c,
+                                                     VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_neon, 0, VPX_BITS_8)));
+#endif
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct16x16_sse2,
+                   &vpx_idct16x16_256_add_sse2, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans16x16HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 0,
+                   VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 1,
+                   VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 2,
+                   VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_sse2, 3,
+                   VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test,
+                        ::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct16x16_sse2,
+                   &idct16x16_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct16x16_c,
+                   &idct16x16_256_add_10_sse2, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct16x16_sse2,
+                   &idct16x16_12, 0, VPX_BITS_12),
+        make_tuple(&vpx_highbd_fdct16x16_c,
+                   &idct16x16_256_add_12_sse2, 0, VPX_BITS_12),
+        make_tuple(&vpx_fdct16x16_sse2,
+                   &vpx_idct16x16_256_add_c, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans16x16HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_sse2, &vp9_iht16x16_256_add_c, 3,
+                   VPX_BITS_8)));
+// Optimizations take effect at a threshold of 3155, so we use a value close to
+// that to test both branches.
+INSTANTIATE_TEST_CASE_P(
+    SSE2, InvTrans16x16DCT,
+    ::testing::Values(
+        make_tuple(&idct16x16_10_add_10_c,
+                   &idct16x16_10_add_10_sse2, 3167, VPX_BITS_10),
+        make_tuple(&idct16x16_10,
+                   &idct16x16_256_add_10_sse2, 3167, VPX_BITS_10),
+        make_tuple(&idct16x16_10_add_12_c,
+                   &idct16x16_10_add_12_sse2, 3167, VPX_BITS_12),
+        make_tuple(&idct16x16_12,
+                   &idct16x16_256_add_12_sse2, 3167, VPX_BITS_12)));
+INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans16x16Test,
+                        ::testing::Values(make_tuple(&vpx_fdct16x16_1_sse2,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    MSA, Trans16x16DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct16x16_msa,
+                   &vpx_idct16x16_256_add_msa, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    MSA, Trans16x16HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht16x16_msa, &vp9_iht16x16_256_add_msa, 3,
+                   VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(MSA, PartialTrans16x16Test,
+                        ::testing::Values(make_tuple(&vpx_fdct16x16_1_msa,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+}  // namespace
diff --git a/src/third_party/libvpx/test/dct32x32_test.cc b/src/third_party/libvpx/test/dct32x32_test.cc
new file mode 100644
index 0000000..16d8825
--- /dev/null
+++ b/src/third_party/libvpx/test/dct32x32_test.cc
@@ -0,0 +1,469 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+#ifdef _MSC_VER
+static int round(double x) {
+  if (x < 0)
+    return static_cast<int>(ceil(x - 0.5));
+  else
+    return static_cast<int>(floor(x + 0.5));
+}
+#endif
+
+const int kNumCoeffs = 1024;
+const double kPi = 3.141592653589793238462643383279502884;
+void reference_32x32_dct_1d(const double in[32], double out[32]) {
+  const double kInvSqrt2 = 0.707106781186547524400844362104;
+  for (int k = 0; k < 32; k++) {
+    out[k] = 0.0;
+    for (int n = 0; n < 32; n++)
+      out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 64.0);
+    if (k == 0)
+      out[k] = out[k] * kInvSqrt2;
+  }
+}
+
+void reference_32x32_dct_2d(const int16_t input[kNumCoeffs],
+                            double output[kNumCoeffs]) {
+  // First transform columns
+  for (int i = 0; i < 32; ++i) {
+    double temp_in[32], temp_out[32];
+    for (int j = 0; j < 32; ++j)
+      temp_in[j] = input[j*32 + i];
+    reference_32x32_dct_1d(temp_in, temp_out);
+    for (int j = 0; j < 32; ++j)
+      output[j * 32 + i] = temp_out[j];
+  }
+  // Then transform rows
+  for (int i = 0; i < 32; ++i) {
+    double temp_in[32], temp_out[32];
+    for (int j = 0; j < 32; ++j)
+      temp_in[j] = output[j + i*32];
+    reference_32x32_dct_1d(temp_in, temp_out);
+    // Scale by some magic number
+    for (int j = 0; j < 32; ++j)
+      output[j + i * 32] = temp_out[j] / 4;
+  }
+}
+
+typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
+
+typedef std::tr1::tuple<FwdTxfmFunc, InvTxfmFunc, int, vpx_bit_depth_t>
+    Trans32x32Param;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct32x32_10(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct32x32_1024_add_c(in, out, stride, 10);
+}
+
+void idct32x32_12(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct32x32_1024_add_c(in, out, stride, 12);
+}
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+class Trans32x32Test : public ::testing::TestWithParam<Trans32x32Param> {
+ public:
+  virtual ~Trans32x32Test() {}
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    version_  = GET_PARAM(2);  // 0: high precision forward transform
+                               // 1: low precision version for rd loop
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  int version_;
+  vpx_bit_depth_t bit_depth_;
+  int mask_;
+  FwdTxfmFunc fwd_txfm_;
+  InvTxfmFunc inv_txfm_;
+};
+
+TEST_P(Trans32x32Test, AccuracyCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  uint32_t max_error = 0;
+  int64_t total_error = 0;
+  const int count_test_block = 10000;
+  DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+  DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+  for (int i = 0; i < count_test_block; ++i) {
+    // Initialize a test block with input range [-mask_, mask_].
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      if (bit_depth_ == VPX_BITS_8) {
+        src[j] = rnd.Rand8();
+        dst[j] = rnd.Rand8();
+        test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        src16[j] = rnd.Rand16() & mask_;
+        dst16[j] = rnd.Rand16() & mask_;
+        test_input_block[j] = src16[j] - dst16[j];
+#endif
+      }
+    }
+
+    ASM_REGISTER_STATE_CHECK(fwd_txfm_(test_input_block, test_temp_block, 32));
+    if (bit_depth_ == VPX_BITS_8) {
+      ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block, dst, 32));
+#if CONFIG_VP9_HIGHBITDEPTH
+    } else {
+      ASM_REGISTER_STATE_CHECK(inv_txfm_(test_temp_block,
+                                         CONVERT_TO_BYTEPTR(dst16), 32));
+#endif
+    }
+
+    for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+      const int32_t diff =
+          bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+      const int32_t diff = dst[j] - src[j];
+#endif
+      const uint32_t error = diff * diff;
+      if (max_error < error)
+        max_error = error;
+      total_error += error;
+    }
+  }
+
+  if (version_ == 1) {
+    max_error /= 2;
+    total_error /= 45;
+  }
+
+  EXPECT_GE(1u << 2 * (bit_depth_ - 8), max_error)
+      << "Error: 32x32 FDCT/IDCT has an individual round-trip error > 1";
+
+  EXPECT_GE(count_test_block << 2 * (bit_depth_ - 8), total_error)
+      << "Error: 32x32 FDCT/IDCT has average round-trip error > 1 per block";
+}
+
+TEST_P(Trans32x32Test, CoeffCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = 1000;
+
+  DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+  for (int i = 0; i < count_test_block; ++i) {
+    for (int j = 0; j < kNumCoeffs; ++j)
+      input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+
+    const int stride = 32;
+    vpx_fdct32x32_c(input_block, output_ref_block, stride);
+    ASM_REGISTER_STATE_CHECK(fwd_txfm_(input_block, output_block, stride));
+
+    if (version_ == 0) {
+      for (int j = 0; j < kNumCoeffs; ++j)
+        EXPECT_EQ(output_block[j], output_ref_block[j])
+            << "Error: 32x32 FDCT versions have mismatched coefficients";
+    } else {
+      for (int j = 0; j < kNumCoeffs; ++j)
+        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
+            << "Error: 32x32 FDCT rd has mismatched coefficients";
+    }
+  }
+}
+
+TEST_P(Trans32x32Test, MemCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = 2000;
+
+  DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+  for (int i = 0; i < count_test_block; ++i) {
+    // Initialize a test block with input range [-mask_, mask_].
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      input_extreme_block[j] = rnd.Rand8() & 1 ? mask_ : -mask_;
+    }
+    if (i == 0) {
+      for (int j = 0; j < kNumCoeffs; ++j)
+        input_extreme_block[j] = mask_;
+    } else if (i == 1) {
+      for (int j = 0; j < kNumCoeffs; ++j)
+        input_extreme_block[j] = -mask_;
+    }
+
+    const int stride = 32;
+    vpx_fdct32x32_c(input_extreme_block, output_ref_block, stride);
+    ASM_REGISTER_STATE_CHECK(
+        fwd_txfm_(input_extreme_block, output_block, stride));
+
+    // The minimum quant value is 4.
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      if (version_ == 0) {
+        EXPECT_EQ(output_block[j], output_ref_block[j])
+            << "Error: 32x32 FDCT versions have mismatched coefficients";
+      } else {
+        EXPECT_GE(6, abs(output_block[j] - output_ref_block[j]))
+            << "Error: 32x32 FDCT rd has mismatched coefficients";
+      }
+      EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_ref_block[j]))
+          << "Error: 32x32 FDCT C has coefficient larger than 4*DCT_MAX_VALUE";
+      EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
+          << "Error: 32x32 FDCT has coefficient larger than "
+          << "4*DCT_MAX_VALUE";
+    }
+  }
+}
+
+TEST_P(Trans32x32Test, InverseAccuracy) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = 1000;
+  DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+  DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+  for (int i = 0; i < count_test_block; ++i) {
+    double out_r[kNumCoeffs];
+
+    // Initialize a test block with input range [-255, 255]
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      if (bit_depth_ == VPX_BITS_8) {
+        src[j] = rnd.Rand8();
+        dst[j] = rnd.Rand8();
+        in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        src16[j] = rnd.Rand16() & mask_;
+        dst16[j] = rnd.Rand16() & mask_;
+        in[j] = src16[j] - dst16[j];
+#endif
+      }
+    }
+
+    reference_32x32_dct_2d(in, out_r);
+    for (int j = 0; j < kNumCoeffs; ++j)
+      coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+    if (bit_depth_ == VPX_BITS_8) {
+      ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, dst, 32));
+#if CONFIG_VP9_HIGHBITDEPTH
+    } else {
+      ASM_REGISTER_STATE_CHECK(inv_txfm_(coeff, CONVERT_TO_BYTEPTR(dst16), 32));
+#endif
+    }
+    for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+      const int diff =
+          bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+      const int diff = dst[j] - src[j];
+#endif
+      const int error = diff * diff;
+      EXPECT_GE(1, error)
+          << "Error: 32x32 IDCT has error " << error
+          << " at index " << j;
+    }
+  }
+}
+
+class PartialTrans32x32Test
+    : public ::testing::TestWithParam<
+          std::tr1::tuple<FwdTxfmFunc, vpx_bit_depth_t> > {
+ public:
+  virtual ~PartialTrans32x32Test() {}
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    bit_depth_ = GET_PARAM(1);
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  vpx_bit_depth_t bit_depth_;
+  FwdTxfmFunc fwd_txfm_;
+};
+
+TEST_P(PartialTrans32x32Test, Extremes) {
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int16_t maxval =
+      static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
+#else
+  const int16_t maxval = 255;
+#endif
+  const int minval = -maxval;
+  DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
+
+  for (int i = 0; i < kNumCoeffs; ++i) input[i] = maxval;
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
+  EXPECT_EQ((maxval * kNumCoeffs) >> 3, output[0]);
+
+  for (int i = 0; i < kNumCoeffs; ++i) input[i] = minval;
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
+  EXPECT_EQ((minval * kNumCoeffs) >> 3, output[0]);
+}
+
+TEST_P(PartialTrans32x32Test, Random) {
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int16_t maxval =
+      static_cast<int16_t>(clip_pixel_highbd(1 << 30, bit_depth_));
+#else
+  const int16_t maxval = 255;
+#endif
+  DECLARE_ALIGNED(16, int16_t, input[kNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output[kNumCoeffs]);
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+  int sum = 0;
+  for (int i = 0; i < kNumCoeffs; ++i) {
+    const int val = (i & 1) ? -rnd(maxval + 1) : rnd(maxval + 1);
+    input[i] = val;
+    sum += val;
+  }
+  output[0] = 0;
+  ASM_REGISTER_STATE_CHECK(fwd_txfm_(input, output, 32));
+  EXPECT_EQ(sum >> 3, output[0]);
+}
+
+using std::tr1::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct32x32_c,
+                   &idct32x32_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct32x32_rd_c,
+                   &idct32x32_10, 1, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct32x32_c,
+                   &idct32x32_12, 0, VPX_BITS_12),
+        make_tuple(&vpx_highbd_fdct32x32_rd_c,
+                   &idct32x32_12, 1, VPX_BITS_12),
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_c,
+                   &vpx_idct32x32_1024_add_c, 1, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    C, PartialTrans32x32Test,
+    ::testing::Values(make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_8),
+                      make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_10),
+                      make_tuple(&vpx_highbd_fdct32x32_1_c, VPX_BITS_12)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_c,
+                   &vpx_idct32x32_1024_add_c, 1, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(C, PartialTrans32x32Test,
+                        ::testing::Values(make_tuple(&vpx_fdct32x32_1_c,
+                                                     VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_neon, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_c,
+                   &vpx_idct32x32_1024_add_neon, 1, VPX_BITS_8)));
+#endif  // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_sse2,
+                   &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_sse2,
+                   &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test,
+                        ::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_10, 1,
+                   VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct32x32_sse2, &idct32x32_12, 0, VPX_BITS_12),
+        make_tuple(&vpx_highbd_fdct32x32_rd_sse2, &idct32x32_12, 1,
+                   VPX_BITS_12),
+        make_tuple(&vpx_fdct32x32_sse2, &vpx_idct32x32_1024_add_c, 0,
+                   VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_sse2, &vpx_idct32x32_1024_add_c, 1,
+                   VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(SSE2, PartialTrans32x32Test,
+                        ::testing::Values(make_tuple(&vpx_fdct32x32_1_sse2,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    AVX2, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_avx2,
+                   &vpx_idct32x32_1024_add_sse2, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_avx2,
+                   &vpx_idct32x32_1024_add_sse2, 1, VPX_BITS_8)));
+#endif  // HAVE_AVX2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    MSA, Trans32x32Test,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_msa,
+                   &vpx_idct32x32_1024_add_msa, 0, VPX_BITS_8),
+        make_tuple(&vpx_fdct32x32_rd_msa,
+                   &vpx_idct32x32_1024_add_msa, 1, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(MSA, PartialTrans32x32Test,
+                        ::testing::Values(make_tuple(&vpx_fdct32x32_1_msa,
+                                                     VPX_BITS_8)));
+#endif  // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+}  // namespace
diff --git a/src/third_party/libvpx/test/decode_api_test.cc b/src/third_party/libvpx/test/decode_api_test.cc
new file mode 100644
index 0000000..318351b
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_api_test.cc
@@ -0,0 +1,151 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "test/ivf_video_source.h"
+#include "vpx/vp8dx.h"
+#include "vpx/vpx_decoder.h"
+
+namespace {
+
+#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
+
+TEST(DecodeAPI, InvalidParams) {
+  static const vpx_codec_iface_t *kCodecs[] = {
+#if CONFIG_VP8_DECODER
+    &vpx_codec_vp8_dx_algo,
+#endif
+#if CONFIG_VP9_DECODER
+    &vpx_codec_vp9_dx_algo,
+#endif
+#if CONFIG_VP10_DECODER
+    &vpx_codec_vp10_dx_algo,
+#endif
+  };
+  uint8_t buf[1] = {0};
+  vpx_codec_ctx_t dec;
+
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(NULL, NULL, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_dec_init(&dec, NULL, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, NULL, 0, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_decode(NULL, buf, 0, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_decode(NULL, buf, NELEMENTS(buf), NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_decode(NULL, NULL, NELEMENTS(buf), NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL));
+  EXPECT_TRUE(vpx_codec_error(NULL) != NULL);
+
+  for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_dec_init(NULL, kCodecs[i], NULL, 0));
+
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, kCodecs[i], NULL, 0));
+    EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
+              vpx_codec_decode(&dec, buf, NELEMENTS(buf), NULL, 0));
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_decode(&dec, NULL, NELEMENTS(buf), NULL, 0));
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_decode(&dec, buf, 0, NULL, 0));
+
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+  }
+}
+
+#if CONFIG_VP8_DECODER
+TEST(DecodeAPI, OptionalParams) {
+  vpx_codec_ctx_t dec;
+
+#if CONFIG_ERROR_CONCEALMENT
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL,
+                                             VPX_CODEC_USE_ERROR_CONCEALMENT));
+#else
+  EXPECT_EQ(VPX_CODEC_INCAPABLE,
+            vpx_codec_dec_init(&dec, &vpx_codec_vp8_dx_algo, NULL,
+                               VPX_CODEC_USE_ERROR_CONCEALMENT));
+#endif  // CONFIG_ERROR_CONCEALMENT
+}
+#endif  // CONFIG_VP8_DECODER
+
+#if CONFIG_VP9_DECODER
+// Test VP9 codec controls after a decode error to ensure the code doesn't
+// misbehave.
+void TestVp9Controls(vpx_codec_ctx_t *dec) {
+  static const int kControls[] = {
+    VP8D_GET_LAST_REF_UPDATES,
+    VP8D_GET_FRAME_CORRUPTED,
+    VP9D_GET_DISPLAY_SIZE,
+    VP9D_GET_FRAME_SIZE
+  };
+  int val[2];
+
+  for (int i = 0; i < NELEMENTS(kControls); ++i) {
+    const vpx_codec_err_t res = vpx_codec_control_(dec, kControls[i], val);
+    switch (kControls[i]) {
+      case VP8D_GET_FRAME_CORRUPTED:
+        EXPECT_EQ(VPX_CODEC_ERROR, res) << kControls[i];
+        break;
+      default:
+        EXPECT_EQ(VPX_CODEC_OK, res) << kControls[i];
+        break;
+    }
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_control_(dec, kControls[i], NULL));
+  }
+
+  vp9_ref_frame_t ref;
+  ref.idx = 0;
+  EXPECT_EQ(VPX_CODEC_ERROR, vpx_codec_control(dec, VP9_GET_REFERENCE, &ref));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_control(dec, VP9_GET_REFERENCE, NULL));
+
+  vpx_ref_frame_t ref_copy;
+  const int width = 352;
+  const int height = 288;
+  ASSERT_TRUE(
+      vpx_img_alloc(&ref_copy.img, VPX_IMG_FMT_I420, width, height, 1) != NULL);
+  ref_copy.frame_type = VP8_LAST_FRAME;
+  EXPECT_EQ(VPX_CODEC_ERROR,
+            vpx_codec_control(dec, VP8_COPY_REFERENCE, &ref_copy));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_control(dec, VP8_COPY_REFERENCE, NULL));
+  vpx_img_free(&ref_copy.img);
+}
+
+TEST(DecodeAPI, Vp9InvalidDecode) {
+  const vpx_codec_iface_t *const codec = &vpx_codec_vp9_dx_algo;
+  const char filename[] =
+      "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf";
+  libvpx_test::IVFVideoSource video(filename);
+  video.Init();
+  video.Begin();
+  ASSERT_TRUE(!HasFailure());
+
+  vpx_codec_ctx_t dec;
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_dec_init(&dec, codec, NULL, 0));
+  const uint32_t frame_size = static_cast<uint32_t>(video.frame_size());
+#if CONFIG_VP9_HIGHBITDEPTH
+  EXPECT_EQ(VPX_CODEC_MEM_ERROR,
+            vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0));
+#else
+  EXPECT_EQ(VPX_CODEC_UNSUP_BITSTREAM,
+            vpx_codec_decode(&dec, video.cxdata(), frame_size, NULL, 0));
+#endif
+  vpx_codec_iter_t iter = NULL;
+  EXPECT_EQ(NULL, vpx_codec_get_frame(&dec, &iter));
+
+  TestVp9Controls(&dec);
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&dec));
+}
+#endif  // CONFIG_VP9_DECODER
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/decode_perf_test.cc b/src/third_party/libvpx/test/decode_perf_test.cc
new file mode 100644
index 0000000..c24d517
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_perf_test.cc
@@ -0,0 +1,273 @@
+/*
+ *  Copyright (c) 2013 The WebM 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>
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/util.h"
+#include "test/webm_video_source.h"
+#include "vpx_ports/vpx_timer.h"
+#include "./ivfenc.h"
+#include "./vpx_version.h"
+
+using std::tr1::make_tuple;
+
+namespace {
+
+#define VIDEO_NAME 0
+#define THREADS 1
+
+const int kMaxPsnr = 100;
+const double kUsecsInSec = 1000000.0;
+const char kNewEncodeOutputFile[] = "new_encode.ivf";
+
+/*
+ DecodePerfTest takes a tuple of filename + number of threads to decode with
+ */
+typedef std::tr1::tuple<const char *, unsigned> DecodePerfParam;
+
+const DecodePerfParam kVP9DecodePerfVectors[] = {
+  make_tuple("vp90-2-bbb_426x240_tile_1x1_180kbps.webm", 1),
+  make_tuple("vp90-2-bbb_640x360_tile_1x2_337kbps.webm", 2),
+  make_tuple("vp90-2-bbb_854x480_tile_1x2_651kbps.webm", 2),
+  make_tuple("vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm", 4),
+  make_tuple("vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm", 1),
+  make_tuple("vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm", 4),
+  make_tuple("vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm", 4),
+  make_tuple("vp90-2-sintel_426x182_tile_1x1_171kbps.webm", 1),
+  make_tuple("vp90-2-sintel_640x272_tile_1x2_318kbps.webm", 2),
+  make_tuple("vp90-2-sintel_854x364_tile_1x2_621kbps.webm", 2),
+  make_tuple("vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm", 4),
+  make_tuple("vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm", 4),
+  make_tuple("vp90-2-tos_426x178_tile_1x1_181kbps.webm", 1),
+  make_tuple("vp90-2-tos_640x266_tile_1x2_336kbps.webm", 2),
+  make_tuple("vp90-2-tos_854x356_tile_1x2_656kbps.webm", 2),
+  make_tuple("vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm", 2),
+  make_tuple("vp90-2-tos_1280x534_tile_1x4_1306kbps.webm", 4),
+  make_tuple("vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm", 4),
+  make_tuple("vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm", 4),
+};
+
+/*
+ In order to reflect real world performance as much as possible, Perf tests
+ *DO NOT* do any correctness checks. Please run them alongside correctness
+ tests to ensure proper codec integrity. Furthermore, in this test we
+ deliberately limit the amount of system calls we make to avoid OS
+ preemption.
+
+ TODO(joshualitt) create a more detailed perf measurement test to collect
+   power/temp/min max frame decode times/etc
+ */
+
+class DecodePerfTest : public ::testing::TestWithParam<DecodePerfParam> {
+};
+
+TEST_P(DecodePerfTest, PerfTest) {
+  const char *const video_name = GET_PARAM(VIDEO_NAME);
+  const unsigned threads = GET_PARAM(THREADS);
+
+  libvpx_test::WebMVideoSource video(video_name);
+  video.Init();
+
+  vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+  cfg.threads = threads;
+  libvpx_test::VP9Decoder decoder(cfg, 0);
+
+  vpx_usec_timer t;
+  vpx_usec_timer_start(&t);
+
+  for (video.Begin(); video.cxdata() != NULL; video.Next()) {
+    decoder.DecodeFrame(video.cxdata(), video.frame_size());
+  }
+
+  vpx_usec_timer_mark(&t);
+  const double elapsed_secs = double(vpx_usec_timer_elapsed(&t))
+                              / kUsecsInSec;
+  const unsigned frames = video.frame_number();
+  const double fps = double(frames) / elapsed_secs;
+
+  printf("{\n");
+  printf("\t\"type\" : \"decode_perf_test\",\n");
+  printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+  printf("\t\"videoName\" : \"%s\",\n", video_name);
+  printf("\t\"threadCount\" : %u,\n", threads);
+  printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
+  printf("\t\"totalFrames\" : %u,\n", frames);
+  printf("\t\"framesPerSecond\" : %f\n", fps);
+  printf("}\n");
+}
+
+INSTANTIATE_TEST_CASE_P(VP9, DecodePerfTest,
+                        ::testing::ValuesIn(kVP9DecodePerfVectors));
+
+class VP9NewEncodeDecodePerfTest :
+    public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  VP9NewEncodeDecodePerfTest()
+      : EncoderTest(GET_PARAM(0)),
+        encoding_mode_(GET_PARAM(1)),
+        speed_(0),
+        outfile_(0),
+        out_frames_(0) {
+  }
+
+  virtual ~VP9NewEncodeDecodePerfTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+
+    cfg_.g_lag_in_frames = 25;
+    cfg_.rc_min_quantizer = 2;
+    cfg_.rc_max_quantizer = 56;
+    cfg_.rc_dropframe_thresh = 0;
+    cfg_.rc_undershoot_pct = 50;
+    cfg_.rc_overshoot_pct = 50;
+    cfg_.rc_buf_sz = 1000;
+    cfg_.rc_buf_initial_sz = 500;
+    cfg_.rc_buf_optimal_sz = 600;
+    cfg_.rc_resize_allowed = 0;
+    cfg_.rc_end_usage = VPX_VBR;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, speed_);
+      encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, 2);
+    }
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    const std::string data_path = getenv("LIBVPX_TEST_DATA_PATH");
+    const std::string path_to_source = data_path + "/" + kNewEncodeOutputFile;
+    outfile_ = fopen(path_to_source.c_str(), "wb");
+    ASSERT_TRUE(outfile_ != NULL);
+  }
+
+  virtual void EndPassHook() {
+    if (outfile_ != NULL) {
+      if (!fseek(outfile_, 0, SEEK_SET))
+        ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
+      fclose(outfile_);
+      outfile_ = NULL;
+    }
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    ++out_frames_;
+
+    // Write initial file header if first frame.
+    if (pkt->data.frame.pts == 0)
+      ivf_write_file_header(outfile_, &cfg_, VP9_FOURCC, out_frames_);
+
+    // Write frame header and data.
+    ivf_write_frame_header(outfile_, out_frames_, pkt->data.frame.sz);
+    ASSERT_EQ(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_),
+              pkt->data.frame.sz);
+  }
+
+  virtual bool DoDecode() { return false; }
+
+  void set_speed(unsigned int speed) {
+    speed_ = speed;
+  }
+
+ private:
+  libvpx_test::TestMode encoding_mode_;
+  uint32_t speed_;
+  FILE *outfile_;
+  uint32_t out_frames_;
+};
+
+struct EncodePerfTestVideo {
+  EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
+                      uint32_t bitrate_, int frames_)
+      : name(name_),
+        width(width_),
+        height(height_),
+        bitrate(bitrate_),
+        frames(frames_) {}
+  const char *name;
+  uint32_t width;
+  uint32_t height;
+  uint32_t bitrate;
+  int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+  EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
+};
+
+TEST_P(VP9NewEncodeDecodePerfTest, PerfTest) {
+  SetUp();
+
+  // TODO(JBB): Make this work by going through the set of given files.
+  const int i = 0;
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  const char *video_name = kVP9EncodePerfTestVectors[i].name;
+  libvpx_test::I420VideoSource video(
+      video_name,
+      kVP9EncodePerfTestVectors[i].width,
+      kVP9EncodePerfTestVectors[i].height,
+      timebase.den, timebase.num, 0,
+      kVP9EncodePerfTestVectors[i].frames);
+  set_speed(2);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  const uint32_t threads = 4;
+
+  libvpx_test::IVFVideoSource decode_video(kNewEncodeOutputFile);
+  decode_video.Init();
+
+  vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+  cfg.threads = threads;
+  libvpx_test::VP9Decoder decoder(cfg, 0);
+
+  vpx_usec_timer t;
+  vpx_usec_timer_start(&t);
+
+  for (decode_video.Begin(); decode_video.cxdata() != NULL;
+       decode_video.Next()) {
+    decoder.DecodeFrame(decode_video.cxdata(), decode_video.frame_size());
+  }
+
+  vpx_usec_timer_mark(&t);
+  const double elapsed_secs =
+      static_cast<double>(vpx_usec_timer_elapsed(&t)) / kUsecsInSec;
+  const unsigned decode_frames = decode_video.frame_number();
+  const double fps = static_cast<double>(decode_frames) / elapsed_secs;
+
+  printf("{\n");
+  printf("\t\"type\" : \"decode_perf_test\",\n");
+  printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+  printf("\t\"videoName\" : \"%s\",\n", kNewEncodeOutputFile);
+  printf("\t\"threadCount\" : %u,\n", threads);
+  printf("\t\"decodeTimeSecs\" : %f,\n", elapsed_secs);
+  printf("\t\"totalFrames\" : %u,\n", decode_frames);
+  printf("\t\"framesPerSecond\" : %f\n", fps);
+  printf("}\n");
+}
+
+VP9_INSTANTIATE_TEST_CASE(
+  VP9NewEncodeDecodePerfTest, ::testing::Values(::libvpx_test::kTwoPassGood));
+}  // namespace
diff --git a/src/third_party/libvpx/test/decode_test_driver.cc b/src/third_party/libvpx/test/decode_test_driver.cc
new file mode 100644
index 0000000..ad861c3
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_test_driver.cc
@@ -0,0 +1,123 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/register_state_check.h"
+#include "test/video_source.h"
+
+namespace libvpx_test {
+
+const char kVP8Name[] = "WebM Project VP8";
+
+vpx_codec_err_t Decoder::PeekStream(const uint8_t *cxdata, size_t size,
+                                    vpx_codec_stream_info_t *stream_info) {
+  return vpx_codec_peek_stream_info(CodecInterface(),
+                                    cxdata, static_cast<unsigned int>(size),
+                                    stream_info);
+}
+
+vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size) {
+  return DecodeFrame(cxdata, size, NULL);
+}
+
+vpx_codec_err_t Decoder::DecodeFrame(const uint8_t *cxdata, size_t size,
+                                     void *user_priv) {
+  vpx_codec_err_t res_dec;
+  InitOnce();
+  API_REGISTER_STATE_CHECK(
+      res_dec = vpx_codec_decode(&decoder_,
+                                 cxdata, static_cast<unsigned int>(size),
+                                 user_priv, 0));
+  return res_dec;
+}
+
+bool Decoder::IsVP8() const {
+  const char *codec_name = GetDecoderName();
+  return strncmp(kVP8Name, codec_name, sizeof(kVP8Name) - 1) == 0;
+}
+
+void DecoderTest::HandlePeekResult(Decoder *const decoder,
+                                   CompressedVideoSource *video,
+                                   const vpx_codec_err_t res_peek) {
+  const bool is_vp8 = decoder->IsVP8();
+  if (is_vp8) {
+    /* Vp8's implementation of PeekStream returns an error if the frame you
+     * pass it is not a keyframe, so we only expect VPX_CODEC_OK on the first
+     * frame, which must be a keyframe. */
+    if (video->frame_number() == 0)
+      ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
+                                        << vpx_codec_err_to_string(res_peek);
+  } else {
+    /* The Vp9 implementation of PeekStream returns an error only if the
+     * data passed to it isn't a valid Vp9 chunk. */
+    ASSERT_EQ(VPX_CODEC_OK, res_peek) << "Peek return failed: "
+                                      << vpx_codec_err_to_string(res_peek);
+  }
+}
+
+void DecoderTest::RunLoop(CompressedVideoSource *video,
+                          const vpx_codec_dec_cfg_t &dec_cfg) {
+  Decoder* const decoder = codec_->CreateDecoder(dec_cfg, flags_, 0);
+  ASSERT_TRUE(decoder != NULL);
+  bool end_of_file = false;
+
+  // Decode frames.
+  for (video->Begin(); !::testing::Test::HasFailure() && !end_of_file;
+       video->Next()) {
+    PreDecodeFrameHook(*video, decoder);
+
+    vpx_codec_stream_info_t stream_info;
+    stream_info.sz = sizeof(stream_info);
+
+    if (video->cxdata() != NULL) {
+      const vpx_codec_err_t res_peek = decoder->PeekStream(video->cxdata(),
+                                                           video->frame_size(),
+                                                           &stream_info);
+      HandlePeekResult(decoder, video, res_peek);
+      ASSERT_FALSE(::testing::Test::HasFailure());
+
+      vpx_codec_err_t res_dec = decoder->DecodeFrame(video->cxdata(),
+                                                     video->frame_size());
+      if (!HandleDecodeResult(res_dec, *video, decoder))
+        break;
+    } else {
+      // Signal end of the file to the decoder.
+      const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
+      ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+      end_of_file = true;
+    }
+
+    DxDataIterator dec_iter = decoder->GetDxData();
+    const vpx_image_t *img = NULL;
+
+    // Get decompressed data
+    while ((img = dec_iter.Next()))
+      DecompressedFrameHook(*img, video->frame_number());
+  }
+  delete decoder;
+}
+
+void DecoderTest::RunLoop(CompressedVideoSource *video) {
+  vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+  RunLoop(video, dec_cfg);
+}
+
+void DecoderTest::set_cfg(const vpx_codec_dec_cfg_t &dec_cfg) {
+  memcpy(&cfg_, &dec_cfg, sizeof(cfg_));
+}
+
+void DecoderTest::set_flags(const vpx_codec_flags_t flags) {
+  flags_ = flags;
+}
+
+}  // namespace libvpx_test
diff --git a/src/third_party/libvpx/test/decode_test_driver.h b/src/third_party/libvpx/test/decode_test_driver.h
new file mode 100644
index 0000000..f566c53
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_test_driver.h
@@ -0,0 +1,181 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_DECODE_TEST_DRIVER_H_
+#define TEST_DECODE_TEST_DRIVER_H_
+#include <cstring>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "vpx/vpx_decoder.h"
+
+namespace libvpx_test {
+
+class CodecFactory;
+class CompressedVideoSource;
+
+// Provides an object to handle decoding output
+class DxDataIterator {
+ public:
+  explicit DxDataIterator(vpx_codec_ctx_t *decoder)
+      : decoder_(decoder), iter_(NULL) {}
+
+  const vpx_image_t *Next() {
+    return vpx_codec_get_frame(decoder_, &iter_);
+  }
+
+ private:
+  vpx_codec_ctx_t  *decoder_;
+  vpx_codec_iter_t  iter_;
+};
+
+// Provides a simplified interface to manage one video decoding.
+// Similar to Encoder class, the exact services should be added
+// as more tests are added.
+class Decoder {
+ public:
+  Decoder(vpx_codec_dec_cfg_t cfg, unsigned long deadline)
+      : cfg_(cfg), flags_(0), deadline_(deadline), init_done_(false) {
+    memset(&decoder_, 0, sizeof(decoder_));
+  }
+
+  Decoder(vpx_codec_dec_cfg_t cfg, const vpx_codec_flags_t flag,
+          unsigned long deadline)  // NOLINT
+      : cfg_(cfg), flags_(flag), deadline_(deadline), init_done_(false) {
+    memset(&decoder_, 0, sizeof(decoder_));
+  }
+
+  virtual ~Decoder() {
+    vpx_codec_destroy(&decoder_);
+  }
+
+  vpx_codec_err_t PeekStream(const uint8_t *cxdata, size_t size,
+                             vpx_codec_stream_info_t *stream_info);
+
+  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size);
+
+  vpx_codec_err_t DecodeFrame(const uint8_t *cxdata, size_t size,
+                              void *user_priv);
+
+  DxDataIterator GetDxData() {
+    return DxDataIterator(&decoder_);
+  }
+
+  void set_deadline(unsigned long deadline) {
+    deadline_ = deadline;
+  }
+
+  void Control(int ctrl_id, int arg) {
+    Control(ctrl_id, arg, VPX_CODEC_OK);
+  }
+
+  void Control(int ctrl_id, const void *arg) {
+    InitOnce();
+    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+  }
+
+  void Control(int ctrl_id, int arg, vpx_codec_err_t expected_value) {
+    InitOnce();
+    const vpx_codec_err_t res = vpx_codec_control_(&decoder_, ctrl_id, arg);
+    ASSERT_EQ(expected_value, res) << DecodeError();
+  }
+
+  const char* DecodeError() {
+    const char *detail = vpx_codec_error_detail(&decoder_);
+    return detail ? detail : vpx_codec_error(&decoder_);
+  }
+
+  // Passes the external frame buffer information to libvpx.
+  vpx_codec_err_t SetFrameBufferFunctions(
+      vpx_get_frame_buffer_cb_fn_t cb_get,
+      vpx_release_frame_buffer_cb_fn_t cb_release, void *user_priv) {
+    InitOnce();
+    return vpx_codec_set_frame_buffer_functions(
+        &decoder_, cb_get, cb_release, user_priv);
+  }
+
+  const char* GetDecoderName() const {
+    return vpx_codec_iface_name(CodecInterface());
+  }
+
+  bool IsVP8() const;
+
+  vpx_codec_ctx_t * GetDecoder() {
+    return &decoder_;
+  }
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const = 0;
+
+  void InitOnce() {
+    if (!init_done_) {
+      const vpx_codec_err_t res = vpx_codec_dec_init(&decoder_,
+                                                     CodecInterface(),
+                                                     &cfg_, flags_);
+      ASSERT_EQ(VPX_CODEC_OK, res) << DecodeError();
+      init_done_ = true;
+    }
+  }
+
+  vpx_codec_ctx_t     decoder_;
+  vpx_codec_dec_cfg_t cfg_;
+  vpx_codec_flags_t   flags_;
+  unsigned int        deadline_;
+  bool                init_done_;
+};
+
+// Common test functionality for all Decoder tests.
+class DecoderTest {
+ public:
+  // Main decoding loop
+  virtual void RunLoop(CompressedVideoSource *video);
+  virtual void RunLoop(CompressedVideoSource *video,
+                       const vpx_codec_dec_cfg_t &dec_cfg);
+
+  virtual void set_cfg(const vpx_codec_dec_cfg_t &dec_cfg);
+  virtual void set_flags(const vpx_codec_flags_t flags);
+
+  // Hook to be called before decompressing every frame.
+  virtual void PreDecodeFrameHook(const CompressedVideoSource& /*video*/,
+                                  Decoder* /*decoder*/) {}
+
+  // Hook to be called to handle decode result. Return true to continue.
+  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+                                  const CompressedVideoSource& /*video*/,
+                                  Decoder *decoder) {
+    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+    return VPX_CODEC_OK == res_dec;
+  }
+
+  // Hook to be called on every decompressed frame.
+  virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
+                                     const unsigned int /*frame_number*/) {}
+
+  // Hook to be called on peek result
+  virtual void HandlePeekResult(Decoder* const decoder,
+                                CompressedVideoSource *video,
+                                const vpx_codec_err_t res_peek);
+
+ protected:
+  explicit DecoderTest(const CodecFactory *codec)
+      : codec_(codec),
+        cfg_(),
+        flags_(0) {}
+
+  virtual ~DecoderTest() {}
+
+  const CodecFactory *codec_;
+  vpx_codec_dec_cfg_t cfg_;
+  vpx_codec_flags_t   flags_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_DECODE_TEST_DRIVER_H_
diff --git a/src/third_party/libvpx/test/decode_to_md5.sh b/src/third_party/libvpx/test/decode_to_md5.sh
new file mode 100755
index 0000000..854b74f
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_to_md5.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx decode_to_md5 example. To add new tests to this
+##  file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to decode_to_md5_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+#   $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+decode_to_md5_verify_environment() {
+  if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Runs decode_to_md5 on $1 and captures the md5 sum for the final frame. $2 is
+# interpreted as codec name and used solely to name the output file. $3 is the
+# expected md5 sum: It must match that of the final frame.
+decode_to_md5() {
+  local decoder="${LIBVPX_BIN_PATH}/decode_to_md5${VPX_TEST_EXE_SUFFIX}"
+  local input_file="$1"
+  local codec="$2"
+  local expected_md5="$3"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/decode_to_md5_${codec}"
+
+  if [ ! -x "${decoder}" ]; then
+    elog "${decoder} does not exist or is not executable."
+    return 1
+  fi
+
+  eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+      ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+
+  local md5_last_frame="$(tail -n1 "${output_file}" | awk '{print $1}')"
+  local actual_md5="$(echo "${md5_last_frame}" | awk '{print $1}')"
+  [ "${actual_md5}" = "${expected_md5}" ] || return 1
+}
+
+decode_to_md5_vp8() {
+  # expected MD5 sum for the last frame.
+  local expected_md5="56794d911b02190212bca92f88ad60c6"
+
+  if [ "$(vp8_decode_available)" = "yes" ]; then
+    decode_to_md5 "${VP8_IVF_FILE}" "vp8" "${expected_md5}"
+  fi
+}
+
+decode_to_md5_vp9() {
+  # expected MD5 sum for the last frame.
+  local expected_md5="2952c0eae93f3dadd1aa84c50d3fd6d2"
+
+  if [ "$(vp9_decode_available)" = "yes" ]; then
+    decode_to_md5 "${VP9_IVF_FILE}" "vp9" "${expected_md5}"
+  fi
+}
+
+decode_to_md5_tests="decode_to_md5_vp8
+                     decode_to_md5_vp9"
+
+run_tests decode_to_md5_verify_environment "${decode_to_md5_tests}"
diff --git a/src/third_party/libvpx/test/decode_with_drops.sh b/src/third_party/libvpx/test/decode_with_drops.sh
new file mode 100755
index 0000000..9b2edb6
--- /dev/null
+++ b/src/third_party/libvpx/test/decode_with_drops.sh
@@ -0,0 +1,79 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx decode_with_drops example. To add new tests to
+##  this file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to decode_with_drops_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+#   $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+decode_with_drops_verify_environment() {
+  if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Runs decode_with_drops on $1, $2 is interpreted as codec name and used solely
+# to name the output file. $3 is the drop mode, and is passed directly to
+# decode_with_drops.
+decode_with_drops() {
+  local decoder="${LIBVPX_BIN_PATH}/decode_with_drops${VPX_TEST_EXE_SUFFIX}"
+  local input_file="$1"
+  local codec="$2"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/decode_with_drops_${codec}"
+  local drop_mode="$3"
+
+  if [ ! -x "${decoder}" ]; then
+    elog "${decoder} does not exist or is not executable."
+    return 1
+  fi
+
+  eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+      "${drop_mode}" ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+}
+
+# Decodes $VP8_IVF_FILE while dropping frames, twice: once in sequence mode,
+# and once in pattern mode.
+# Note: This test assumes that $VP8_IVF_FILE has exactly 29 frames, and could
+# break if the file is modified.
+decode_with_drops_vp8() {
+  if [ "$(vp8_decode_available)" = "yes" ]; then
+    # Test sequence mode: Drop frames 2-28.
+    decode_with_drops "${VP8_IVF_FILE}" "vp8" "2-28"
+
+    # Test pattern mode: Drop 3 of every 4 frames.
+    decode_with_drops "${VP8_IVF_FILE}" "vp8" "3/4"
+  fi
+}
+
+# Decodes $VP9_IVF_FILE while dropping frames, twice: once in sequence mode,
+# and once in pattern mode.
+# Note: This test assumes that $VP9_IVF_FILE has exactly 20 frames, and could
+# break if the file is modified.
+decode_with_drops_vp9() {
+  if [ "$(vp9_decode_available)" = "yes" ]; then
+    # Test sequence mode: Drop frames 2-28.
+    decode_with_drops "${VP9_IVF_FILE}" "vp9" "2-19"
+
+    # Test pattern mode: Drop 3 of every 4 frames.
+    decode_with_drops "${VP9_IVF_FILE}" "vp9" "3/4"
+  fi
+}
+
+decode_with_drops_tests="decode_with_drops_vp8
+                         decode_with_drops_vp9"
+
+run_tests decode_with_drops_verify_environment "${decode_with_drops_tests}"
diff --git a/src/third_party/libvpx/test/encode_api_test.cc b/src/third_party/libvpx/test/encode_api_test.cc
new file mode 100644
index 0000000..a7200e6
--- /dev/null
+++ b/src/third_party/libvpx/test/encode_api_test.cc
@@ -0,0 +1,68 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+namespace {
+
+#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
+
+TEST(EncodeAPI, InvalidParams) {
+  static const vpx_codec_iface_t *kCodecs[] = {
+#if CONFIG_VP8_ENCODER
+    &vpx_codec_vp8_cx_algo,
+#endif
+#if CONFIG_VP9_ENCODER
+    &vpx_codec_vp9_cx_algo,
+#endif
+#if CONFIG_VP10_ENCODER
+    &vpx_codec_vp10_cx_algo,
+#endif
+  };
+  uint8_t buf[1] = {0};
+  vpx_image_t img;
+  vpx_codec_ctx_t enc;
+  vpx_codec_enc_cfg_t cfg;
+
+  EXPECT_EQ(&img, vpx_img_wrap(&img, VPX_IMG_FMT_I420, 1, 1, 1, buf));
+
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(NULL, NULL, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_enc_init(&enc, NULL, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, NULL, 0, 0, 0, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_encode(NULL, &img, 0, 0, 0, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, vpx_codec_destroy(NULL));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_enc_config_default(NULL, NULL, 0));
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+            vpx_codec_enc_config_default(NULL, &cfg, 0));
+  EXPECT_TRUE(vpx_codec_error(NULL) != NULL);
+
+  for (int i = 0; i < NELEMENTS(kCodecs); ++i) {
+    SCOPED_TRACE(vpx_codec_iface_name(kCodecs[i]));
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_enc_init(NULL, kCodecs[i], NULL, 0));
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_enc_init(&enc, kCodecs[i], NULL, 0));
+    EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+              vpx_codec_enc_config_default(kCodecs[i], &cfg, 1));
+
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(kCodecs[i], &cfg, 0));
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, kCodecs[i], &cfg, 0));
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_encode(&enc, NULL, 0, 0, 0, 0));
+
+    EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc));
+  }
+}
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/encode_perf_test.cc b/src/third_party/libvpx/test/encode_perf_test.cc
new file mode 100644
index 0000000..7e9f0d6
--- /dev/null
+++ b/src/third_party/libvpx/test/encode_perf_test.cc
@@ -0,0 +1,202 @@
+/*
+ *  Copyright (c) 2014 The WebM 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>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "./vpx_version.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+#include "test/y4m_video_source.h"
+#include "vpx_ports/vpx_timer.h"
+
+namespace {
+
+const int kMaxPsnr = 100;
+const double kUsecsInSec = 1000000.0;
+
+struct EncodePerfTestVideo {
+  EncodePerfTestVideo(const char *name_, uint32_t width_, uint32_t height_,
+                      uint32_t bitrate_, int frames_)
+      : name(name_),
+        width(width_),
+        height(height_),
+        bitrate(bitrate_),
+        frames(frames_) {}
+  const char *name;
+  uint32_t width;
+  uint32_t height;
+  uint32_t bitrate;
+  int frames;
+};
+
+const EncodePerfTestVideo kVP9EncodePerfTestVectors[] = {
+  EncodePerfTestVideo("desktop_640_360_30.yuv", 640, 360, 200, 2484),
+  EncodePerfTestVideo("kirland_640_480_30.yuv", 640, 480, 200, 300),
+  EncodePerfTestVideo("macmarcomoving_640_480_30.yuv", 640, 480, 200, 987),
+  EncodePerfTestVideo("macmarcostationary_640_480_30.yuv", 640, 480, 200, 718),
+  EncodePerfTestVideo("niklas_640_480_30.yuv", 640, 480, 200, 471),
+  EncodePerfTestVideo("tacomanarrows_640_480_30.yuv", 640, 480, 200, 300),
+  EncodePerfTestVideo("tacomasmallcameramovement_640_480_30.yuv",
+                      640, 480, 200, 300),
+  EncodePerfTestVideo("thaloundeskmtg_640_480_30.yuv", 640, 480, 200, 300),
+  EncodePerfTestVideo("niklas_1280_720_30.yuv", 1280, 720, 600, 470),
+};
+
+const int kEncodePerfTestSpeeds[] = { 5, 6, 7, 8 };
+const int kEncodePerfTestThreads[] = { 1, 2, 4 };
+
+#define NELEMENTS(x) (sizeof((x)) / sizeof((x)[0]))
+
+class VP9EncodePerfTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  VP9EncodePerfTest()
+      : EncoderTest(GET_PARAM(0)),
+        min_psnr_(kMaxPsnr),
+        nframes_(0),
+        encoding_mode_(GET_PARAM(1)),
+        speed_(0),
+        threads_(1) {}
+
+  virtual ~VP9EncodePerfTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+
+    cfg_.g_lag_in_frames = 0;
+    cfg_.rc_min_quantizer = 2;
+    cfg_.rc_max_quantizer = 56;
+    cfg_.rc_dropframe_thresh = 0;
+    cfg_.rc_undershoot_pct = 50;
+    cfg_.rc_overshoot_pct = 50;
+    cfg_.rc_buf_sz = 1000;
+    cfg_.rc_buf_initial_sz = 500;
+    cfg_.rc_buf_optimal_sz = 600;
+    cfg_.rc_resize_allowed = 0;
+    cfg_.rc_end_usage = VPX_CBR;
+    cfg_.g_error_resilient = 1;
+    cfg_.g_threads = threads_;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      const int log2_tile_columns = 3;
+      encoder->Control(VP8E_SET_CPUUSED, speed_);
+      encoder->Control(VP9E_SET_TILE_COLUMNS, log2_tile_columns);
+      encoder->Control(VP9E_SET_FRAME_PARALLEL_DECODING, 1);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 0);
+    }
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    min_psnr_ = kMaxPsnr;
+    nframes_ = 0;
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.psnr.psnr[0] < min_psnr_) {
+      min_psnr_= pkt->data.psnr.psnr[0];
+    }
+  }
+
+  // for performance reasons don't decode
+  virtual bool DoDecode() { return 0; }
+
+  double min_psnr() const {
+    return min_psnr_;
+  }
+
+  void set_speed(unsigned int speed) {
+    speed_ = speed;
+  }
+
+  void set_threads(unsigned int threads) {
+    threads_ = threads;
+  }
+
+ private:
+  double min_psnr_;
+  unsigned int nframes_;
+  libvpx_test::TestMode encoding_mode_;
+  unsigned speed_;
+  unsigned int threads_;
+};
+
+TEST_P(VP9EncodePerfTest, PerfTest) {
+  for (size_t i = 0; i < NELEMENTS(kVP9EncodePerfTestVectors); ++i) {
+    for (size_t j = 0; j < NELEMENTS(kEncodePerfTestSpeeds); ++j) {
+      for (size_t k = 0; k < NELEMENTS(kEncodePerfTestThreads); ++k) {
+        if (kVP9EncodePerfTestVectors[i].width < 512 &&
+            kEncodePerfTestThreads[k] > 1)
+          continue;
+        else if (kVP9EncodePerfTestVectors[i].width < 1024 &&
+                 kEncodePerfTestThreads[k] > 2)
+          continue;
+
+        set_threads(kEncodePerfTestThreads[k]);
+        SetUp();
+
+        const vpx_rational timebase = { 33333333, 1000000000 };
+        cfg_.g_timebase = timebase;
+        cfg_.rc_target_bitrate = kVP9EncodePerfTestVectors[i].bitrate;
+
+        init_flags_ = VPX_CODEC_USE_PSNR;
+
+        const unsigned frames = kVP9EncodePerfTestVectors[i].frames;
+        const char *video_name = kVP9EncodePerfTestVectors[i].name;
+        libvpx_test::I420VideoSource video(
+            video_name,
+            kVP9EncodePerfTestVectors[i].width,
+            kVP9EncodePerfTestVectors[i].height,
+            timebase.den, timebase.num, 0,
+            kVP9EncodePerfTestVectors[i].frames);
+        set_speed(kEncodePerfTestSpeeds[j]);
+
+        vpx_usec_timer t;
+        vpx_usec_timer_start(&t);
+
+        ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+        vpx_usec_timer_mark(&t);
+        const double elapsed_secs = vpx_usec_timer_elapsed(&t) / kUsecsInSec;
+        const double fps = frames / elapsed_secs;
+        const double minimum_psnr = min_psnr();
+        std::string display_name(video_name);
+        if (kEncodePerfTestThreads[k] > 1) {
+          char thread_count[32];
+          snprintf(thread_count, sizeof(thread_count), "_t-%d",
+                   kEncodePerfTestThreads[k]);
+          display_name += thread_count;
+        }
+
+        printf("{\n");
+        printf("\t\"type\" : \"encode_perf_test\",\n");
+        printf("\t\"version\" : \"%s\",\n", VERSION_STRING_NOSP);
+        printf("\t\"videoName\" : \"%s\",\n", display_name.c_str());
+        printf("\t\"encodeTimeSecs\" : %f,\n", elapsed_secs);
+        printf("\t\"totalFrames\" : %u,\n", frames);
+        printf("\t\"framesPerSecond\" : %f,\n", fps);
+        printf("\t\"minPsnr\" : %f,\n", minimum_psnr);
+        printf("\t\"speed\" : %d,\n", kEncodePerfTestSpeeds[j]);
+        printf("\t\"threads\" : %d\n", kEncodePerfTestThreads[k]);
+        printf("}\n");
+      }
+    }
+  }
+}
+
+VP9_INSTANTIATE_TEST_CASE(
+    VP9EncodePerfTest, ::testing::Values(::libvpx_test::kRealTime));
+}  // namespace
diff --git a/src/third_party/libvpx/test/encode_test_driver.cc b/src/third_party/libvpx/test/encode_test_driver.cc
new file mode 100644
index 0000000..128436e
--- /dev/null
+++ b/src/third_party/libvpx/test/encode_test_driver.cc
@@ -0,0 +1,282 @@
+/*
+ *  Copyright (c) 2012 The WebM 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>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/encode_test_driver.h"
+#include "test/register_state_check.h"
+#include "test/video_source.h"
+
+namespace libvpx_test {
+void Encoder::InitEncoder(VideoSource *video) {
+  vpx_codec_err_t res;
+  const vpx_image_t *img = video->img();
+
+  if (video->img() && !encoder_.priv) {
+    cfg_.g_w = img->d_w;
+    cfg_.g_h = img->d_h;
+    cfg_.g_timebase = video->timebase();
+    cfg_.rc_twopass_stats_in = stats_->buf();
+
+    res = vpx_codec_enc_init(&encoder_, CodecInterface(), &cfg_,
+                             init_flags_);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+
+#if CONFIG_VP9_ENCODER
+    if (CodecInterface() == &vpx_codec_vp9_cx_algo) {
+      // Default to 1 tile column for VP9.
+      const int log2_tile_columns = 0;
+      res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS,
+                               log2_tile_columns);
+      ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+    } else
+#endif
+#if CONFIG_VP10_ENCODER
+    if (CodecInterface() == &vpx_codec_vp10_cx_algo) {
+      // Default to 1 tile column for VP10.
+      const int log2_tile_columns = 0;
+      res = vpx_codec_control_(&encoder_, VP9E_SET_TILE_COLUMNS,
+                               log2_tile_columns);
+      ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+    } else
+#endif
+    {
+#if CONFIG_VP8_ENCODER
+      ASSERT_EQ(&vpx_codec_vp8_cx_algo, CodecInterface())
+          << "Unknown Codec Interface";
+#endif
+    }
+  }
+}
+
+void Encoder::EncodeFrame(VideoSource *video, const unsigned long frame_flags) {
+  if (video->img())
+    EncodeFrameInternal(*video, frame_flags);
+  else
+    Flush();
+
+  // Handle twopass stats
+  CxDataIterator iter = GetCxData();
+
+  while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+    if (pkt->kind != VPX_CODEC_STATS_PKT)
+      continue;
+
+    stats_->Append(*pkt);
+  }
+}
+
+void Encoder::EncodeFrameInternal(const VideoSource &video,
+                                  const unsigned long frame_flags) {
+  vpx_codec_err_t res;
+  const vpx_image_t *img = video.img();
+
+  // Handle frame resizing
+  if (cfg_.g_w != img->d_w || cfg_.g_h != img->d_h) {
+    cfg_.g_w = img->d_w;
+    cfg_.g_h = img->d_h;
+    res = vpx_codec_enc_config_set(&encoder_, &cfg_);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  // Encode the frame
+  API_REGISTER_STATE_CHECK(
+      res = vpx_codec_encode(&encoder_, img, video.pts(), video.duration(),
+                             frame_flags, deadline_));
+  ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void Encoder::Flush() {
+  const vpx_codec_err_t res = vpx_codec_encode(&encoder_, NULL, 0, 0, 0,
+                                               deadline_);
+  if (!encoder_.priv)
+    ASSERT_EQ(VPX_CODEC_ERROR, res) << EncoderError();
+  else
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+}
+
+void EncoderTest::InitializeConfig() {
+  const vpx_codec_err_t res = codec_->DefaultEncoderConfig(&cfg_, 0);
+  dec_cfg_ = vpx_codec_dec_cfg_t();
+  ASSERT_EQ(VPX_CODEC_OK, res);
+}
+
+void EncoderTest::SetMode(TestMode mode) {
+  switch (mode) {
+    case kRealTime:
+      deadline_ = VPX_DL_REALTIME;
+      break;
+
+    case kOnePassGood:
+    case kTwoPassGood:
+      deadline_ = VPX_DL_GOOD_QUALITY;
+      break;
+
+    case kOnePassBest:
+    case kTwoPassBest:
+      deadline_ = VPX_DL_BEST_QUALITY;
+      break;
+
+    default:
+      ASSERT_TRUE(false) << "Unexpected mode " << mode;
+  }
+
+  if (mode == kTwoPassGood || mode == kTwoPassBest)
+    passes_ = 2;
+  else
+    passes_ = 1;
+}
+// The function should return "true" most of the time, therefore no early
+// break-out is implemented within the match checking process.
+static bool compare_img(const vpx_image_t *img1,
+                        const vpx_image_t *img2) {
+  bool match = (img1->fmt == img2->fmt) &&
+               (img1->cs == img2->cs) &&
+               (img1->d_w == img2->d_w) &&
+               (img1->d_h == img2->d_h);
+
+  const unsigned int width_y  = img1->d_w;
+  const unsigned int height_y = img1->d_h;
+  unsigned int i;
+  for (i = 0; i < height_y; ++i)
+    match = (memcmp(img1->planes[VPX_PLANE_Y] + i * img1->stride[VPX_PLANE_Y],
+                    img2->planes[VPX_PLANE_Y] + i * img2->stride[VPX_PLANE_Y],
+                    width_y) == 0) && match;
+  const unsigned int width_uv  = (img1->d_w + 1) >> 1;
+  const unsigned int height_uv = (img1->d_h + 1) >> 1;
+  for (i = 0; i <  height_uv; ++i)
+    match = (memcmp(img1->planes[VPX_PLANE_U] + i * img1->stride[VPX_PLANE_U],
+                    img2->planes[VPX_PLANE_U] + i * img2->stride[VPX_PLANE_U],
+                    width_uv) == 0) && match;
+  for (i = 0; i < height_uv; ++i)
+    match = (memcmp(img1->planes[VPX_PLANE_V] + i * img1->stride[VPX_PLANE_V],
+                    img2->planes[VPX_PLANE_V] + i * img2->stride[VPX_PLANE_V],
+                    width_uv) == 0) && match;
+  return match;
+}
+
+void EncoderTest::MismatchHook(const vpx_image_t* /*img1*/,
+                               const vpx_image_t* /*img2*/) {
+  ASSERT_TRUE(0) << "Encode/Decode mismatch found";
+}
+
+void EncoderTest::RunLoop(VideoSource *video) {
+  vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+
+  stats_.Reset();
+
+  ASSERT_TRUE(passes_ == 1 || passes_ == 2);
+  for (unsigned int pass = 0; pass < passes_; pass++) {
+    last_pts_ = 0;
+
+    if (passes_ == 1)
+      cfg_.g_pass = VPX_RC_ONE_PASS;
+    else if (pass == 0)
+      cfg_.g_pass = VPX_RC_FIRST_PASS;
+    else
+      cfg_.g_pass = VPX_RC_LAST_PASS;
+
+    BeginPassHook(pass);
+    Encoder* const encoder = codec_->CreateEncoder(cfg_, deadline_, init_flags_,
+                                                   &stats_);
+    ASSERT_TRUE(encoder != NULL);
+
+    video->Begin();
+    encoder->InitEncoder(video);
+    ASSERT_FALSE(::testing::Test::HasFatalFailure());
+
+    unsigned long dec_init_flags = 0;  // NOLINT
+    // Use fragment decoder if encoder outputs partitions.
+    // NOTE: fragment decoder and partition encoder are only supported by VP8.
+    if (init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION)
+      dec_init_flags |= VPX_CODEC_USE_INPUT_FRAGMENTS;
+    Decoder* const decoder = codec_->CreateDecoder(dec_cfg, dec_init_flags, 0);
+    bool again;
+    for (again = true; again; video->Next()) {
+      again = (video->img() != NULL);
+
+      PreEncodeFrameHook(video);
+      PreEncodeFrameHook(video, encoder);
+      encoder->EncodeFrame(video, frame_flags_);
+
+      CxDataIterator iter = encoder->GetCxData();
+
+      bool has_cxdata = false;
+      bool has_dxdata = false;
+      while (const vpx_codec_cx_pkt_t *pkt = iter.Next()) {
+        pkt = MutateEncoderOutputHook(pkt);
+        again = true;
+        switch (pkt->kind) {
+          case VPX_CODEC_CX_FRAME_PKT:
+            has_cxdata = true;
+            if (decoder && DoDecode()) {
+              vpx_codec_err_t res_dec = decoder->DecodeFrame(
+                  (const uint8_t*)pkt->data.frame.buf, pkt->data.frame.sz);
+
+              if (!HandleDecodeResult(res_dec, *video, decoder))
+                break;
+
+              has_dxdata = true;
+            }
+            ASSERT_GE(pkt->data.frame.pts, last_pts_);
+            last_pts_ = pkt->data.frame.pts;
+            FramePktHook(pkt);
+            break;
+
+          case VPX_CODEC_PSNR_PKT:
+            PSNRPktHook(pkt);
+            break;
+
+          default:
+            break;
+        }
+      }
+
+      // Flush the decoder when there are no more fragments.
+      if ((init_flags_ & VPX_CODEC_USE_OUTPUT_PARTITION) && has_dxdata) {
+        const vpx_codec_err_t res_dec = decoder->DecodeFrame(NULL, 0);
+        if (!HandleDecodeResult(res_dec, *video, decoder))
+          break;
+      }
+
+      if (has_dxdata && has_cxdata) {
+        const vpx_image_t *img_enc = encoder->GetPreviewFrame();
+        DxDataIterator dec_iter = decoder->GetDxData();
+        const vpx_image_t *img_dec = dec_iter.Next();
+        if (img_enc && img_dec) {
+          const bool res = compare_img(img_enc, img_dec);
+          if (!res) {  // Mismatch
+            MismatchHook(img_enc, img_dec);
+          }
+        }
+        if (img_dec)
+          DecompressedFrameHook(*img_dec, video->pts());
+      }
+      if (!Continue())
+        break;
+    }
+
+    EndPassHook();
+
+    if (decoder)
+      delete decoder;
+    delete encoder;
+
+    if (!Continue())
+      break;
+  }
+}
+
+}  // namespace libvpx_test
diff --git a/src/third_party/libvpx/test/encode_test_driver.h b/src/third_party/libvpx/test/encode_test_driver.h
new file mode 100644
index 0000000..6d0a72f
--- /dev/null
+++ b/src/third_party/libvpx/test/encode_test_driver.h
@@ -0,0 +1,278 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_ENCODE_TEST_DRIVER_H_
+#define TEST_ENCODE_TEST_DRIVER_H_
+
+#include <string>
+#include <vector>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
+#include "vpx/vp8cx.h"
+#endif
+#include "vpx/vpx_encoder.h"
+
+namespace libvpx_test {
+
+class CodecFactory;
+class VideoSource;
+
+enum TestMode {
+  kRealTime,
+  kOnePassGood,
+  kOnePassBest,
+  kTwoPassGood,
+  kTwoPassBest
+};
+#define ALL_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
+                                         ::libvpx_test::kOnePassGood, \
+                                         ::libvpx_test::kOnePassBest, \
+                                         ::libvpx_test::kTwoPassGood, \
+                                         ::libvpx_test::kTwoPassBest)
+
+#define ONE_PASS_TEST_MODES ::testing::Values(::libvpx_test::kRealTime, \
+                                              ::libvpx_test::kOnePassGood, \
+                                              ::libvpx_test::kOnePassBest)
+
+#define TWO_PASS_TEST_MODES ::testing::Values(::libvpx_test::kTwoPassGood, \
+                                              ::libvpx_test::kTwoPassBest)
+
+
+// Provides an object to handle the libvpx get_cx_data() iteration pattern
+class CxDataIterator {
+ public:
+  explicit CxDataIterator(vpx_codec_ctx_t *encoder)
+      : encoder_(encoder), iter_(NULL) {}
+
+  const vpx_codec_cx_pkt_t *Next() {
+    return vpx_codec_get_cx_data(encoder_, &iter_);
+  }
+
+ private:
+  vpx_codec_ctx_t  *encoder_;
+  vpx_codec_iter_t  iter_;
+};
+
+// Implements an in-memory store for libvpx twopass statistics
+class TwopassStatsStore {
+ public:
+  void Append(const vpx_codec_cx_pkt_t &pkt) {
+    buffer_.append(reinterpret_cast<char *>(pkt.data.twopass_stats.buf),
+                   pkt.data.twopass_stats.sz);
+  }
+
+  vpx_fixed_buf_t buf() {
+    const vpx_fixed_buf_t buf = { &buffer_[0], buffer_.size() };
+    return buf;
+  }
+
+  void Reset() {
+    buffer_.clear();
+  }
+
+ protected:
+  std::string  buffer_;
+};
+
+
+// Provides a simplified interface to manage one video encoding pass, given
+// a configuration and video source.
+//
+// TODO(jkoleszar): The exact services it provides and the appropriate
+// level of abstraction will be fleshed out as more tests are written.
+class Encoder {
+ public:
+  Encoder(vpx_codec_enc_cfg_t cfg, unsigned long deadline,
+          const unsigned long init_flags, TwopassStatsStore *stats)
+      : cfg_(cfg), deadline_(deadline), init_flags_(init_flags), stats_(stats) {
+    memset(&encoder_, 0, sizeof(encoder_));
+  }
+
+  virtual ~Encoder() {
+    vpx_codec_destroy(&encoder_);
+  }
+
+  CxDataIterator GetCxData() {
+    return CxDataIterator(&encoder_);
+  }
+
+  void InitEncoder(VideoSource *video);
+
+  const vpx_image_t *GetPreviewFrame() {
+    return vpx_codec_get_preview_frame(&encoder_);
+  }
+  // This is a thin wrapper around vpx_codec_encode(), so refer to
+  // vpx_encoder.h for its semantics.
+  void EncodeFrame(VideoSource *video, const unsigned long frame_flags);
+
+  // Convenience wrapper for EncodeFrame()
+  void EncodeFrame(VideoSource *video) {
+    EncodeFrame(video, 0);
+  }
+
+  void Control(int ctrl_id, int arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  void Control(int ctrl_id, int *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  void Control(int ctrl_id, struct vpx_scaling_mode *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  void Control(int ctrl_id, struct vpx_svc_layer_id *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+
+  void Control(int ctrl_id, struct vpx_svc_parameters *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER || CONFIG_VP10_ENCODER
+  void Control(int ctrl_id, vpx_active_map_t *arg) {
+    const vpx_codec_err_t res = vpx_codec_control_(&encoder_, ctrl_id, arg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+  }
+#endif
+
+  void Config(const vpx_codec_enc_cfg_t *cfg) {
+    const vpx_codec_err_t res = vpx_codec_enc_config_set(&encoder_, cfg);
+    ASSERT_EQ(VPX_CODEC_OK, res) << EncoderError();
+    cfg_ = *cfg;
+  }
+
+  void set_deadline(unsigned long deadline) {
+    deadline_ = deadline;
+  }
+
+ protected:
+  virtual vpx_codec_iface_t* CodecInterface() const = 0;
+
+  const char *EncoderError() {
+    const char *detail = vpx_codec_error_detail(&encoder_);
+    return detail ? detail : vpx_codec_error(&encoder_);
+  }
+
+  // Encode an image
+  void EncodeFrameInternal(const VideoSource &video,
+                           const unsigned long frame_flags);
+
+  // Flush the encoder on EOS
+  void Flush();
+
+  vpx_codec_ctx_t      encoder_;
+  vpx_codec_enc_cfg_t  cfg_;
+  unsigned long        deadline_;
+  unsigned long        init_flags_;
+  TwopassStatsStore   *stats_;
+};
+
+// Common test functionality for all Encoder tests.
+//
+// This class is a mixin which provides the main loop common to all
+// encoder tests. It provides hooks which can be overridden by subclasses
+// to implement each test's specific behavior, while centralizing the bulk
+// of the boilerplate. Note that it doesn't inherit the gtest testing
+// classes directly, so that tests can be parameterized differently.
+class EncoderTest {
+ protected:
+  explicit EncoderTest(const CodecFactory *codec)
+      : codec_(codec), abort_(false), init_flags_(0), frame_flags_(0),
+        last_pts_(0) {
+    // Default to 1 thread.
+    cfg_.g_threads = 1;
+  }
+
+  virtual ~EncoderTest() {}
+
+  // Initialize the cfg_ member with the default configuration.
+  void InitializeConfig();
+
+  // Map the TestMode enum to the deadline_ and passes_ variables.
+  void SetMode(TestMode mode);
+
+  // Set encoder flag.
+  void set_init_flags(unsigned long flag) {  // NOLINT(runtime/int)
+    init_flags_ = flag;
+  }
+
+  // Main loop
+  virtual void RunLoop(VideoSource *video);
+
+  // Hook to be called at the beginning of a pass.
+  virtual void BeginPassHook(unsigned int /*pass*/) {}
+
+  // Hook to be called at the end of a pass.
+  virtual void EndPassHook() {}
+
+  // Hook to be called before encoding a frame.
+  virtual void PreEncodeFrameHook(VideoSource* /*video*/) {}
+  virtual void PreEncodeFrameHook(VideoSource* /*video*/,
+                                  Encoder* /*encoder*/) {}
+
+  // Hook to be called on every compressed data packet.
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}
+
+  // Hook to be called on every PSNR packet.
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t* /*pkt*/) {}
+
+  // Hook to determine whether the encode loop should continue.
+  virtual bool Continue() const {
+    return !(::testing::Test::HasFatalFailure() || abort_);
+  }
+
+  const CodecFactory   *codec_;
+  // Hook to determine whether to decode frame after encoding
+  virtual bool DoDecode() const { return 1; }
+
+  // Hook to handle encode/decode mismatch
+  virtual void MismatchHook(const vpx_image_t *img1,
+                            const vpx_image_t *img2);
+
+  // Hook to be called on every decompressed frame.
+  virtual void DecompressedFrameHook(const vpx_image_t& /*img*/,
+                                     vpx_codec_pts_t /*pts*/) {}
+
+  // Hook to be called to handle decode result. Return true to continue.
+  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+                                  const VideoSource& /*video*/,
+                                  Decoder *decoder) {
+    EXPECT_EQ(VPX_CODEC_OK, res_dec) << decoder->DecodeError();
+    return VPX_CODEC_OK == res_dec;
+  }
+
+  // Hook that can modify the encoder's output data
+  virtual const vpx_codec_cx_pkt_t *MutateEncoderOutputHook(
+      const vpx_codec_cx_pkt_t *pkt) {
+    return pkt;
+  }
+
+  bool                 abort_;
+  vpx_codec_enc_cfg_t  cfg_;
+  vpx_codec_dec_cfg_t  dec_cfg_;
+  unsigned int         passes_;
+  unsigned long        deadline_;
+  TwopassStatsStore    stats_;
+  unsigned long        init_flags_;
+  unsigned long        frame_flags_;
+  vpx_codec_pts_t      last_pts_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_ENCODE_TEST_DRIVER_H_
diff --git a/src/third_party/libvpx/test/error_resilience_test.cc b/src/third_party/libvpx/test/error_resilience_test.cc
new file mode 100644
index 0000000..cd0dca2
--- /dev/null
+++ b/src/third_party/libvpx/test/error_resilience_test.cc
@@ -0,0 +1,602 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+const int kMaxErrorFrames = 12;
+const int kMaxDroppableFrames = 12;
+
+class ErrorResilienceTestLarge : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, bool> {
+ protected:
+  ErrorResilienceTestLarge()
+      : EncoderTest(GET_PARAM(0)),
+        svc_support_(GET_PARAM(2)),
+        psnr_(0.0),
+        nframes_(0),
+        mismatch_psnr_(0.0),
+        mismatch_nframes_(0),
+        encoding_mode_(GET_PARAM(1)) {
+    Reset();
+  }
+
+  virtual ~ErrorResilienceTestLarge() {}
+
+  void Reset() {
+    error_nframes_ = 0;
+    droppable_nframes_ = 0;
+    pattern_switch_ = 0;
+  }
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    psnr_ = 0.0;
+    nframes_ = 0;
+    mismatch_psnr_ = 0.0;
+    mismatch_nframes_ = 0;
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    psnr_ += pkt->data.psnr.psnr[0];
+    nframes_++;
+  }
+
+  //
+  // Frame flags and layer id for temporal layers.
+  // For two layers, test pattern is:
+  //   1     3
+  // 0    2     .....
+  // LAST is updated on base/layer 0, GOLDEN  updated on layer 1.
+  // Non-zero pattern_switch parameter means pattern will switch to
+  // not using LAST for frame_num >= pattern_switch.
+  int SetFrameFlags(int frame_num,
+                    int num_temp_layers,
+                    int pattern_switch) {
+    int frame_flags = 0;
+    if (num_temp_layers == 2) {
+        if (frame_num % 2 == 0) {
+          if (frame_num < pattern_switch || pattern_switch == 0) {
+            // Layer 0: predict from LAST and ARF, update LAST.
+            frame_flags = VP8_EFLAG_NO_REF_GF |
+                          VP8_EFLAG_NO_UPD_GF |
+                          VP8_EFLAG_NO_UPD_ARF;
+          } else {
+            // Layer 0: predict from GF and ARF, update GF.
+            frame_flags = VP8_EFLAG_NO_REF_LAST |
+                          VP8_EFLAG_NO_UPD_LAST |
+                          VP8_EFLAG_NO_UPD_ARF;
+          }
+        } else {
+          if (frame_num < pattern_switch || pattern_switch == 0) {
+            // Layer 1: predict from L, GF, and ARF, update GF.
+            frame_flags = VP8_EFLAG_NO_UPD_ARF |
+                          VP8_EFLAG_NO_UPD_LAST;
+          } else {
+            // Layer 1: predict from GF and ARF, update GF.
+            frame_flags = VP8_EFLAG_NO_REF_LAST |
+                          VP8_EFLAG_NO_UPD_LAST |
+                          VP8_EFLAG_NO_UPD_ARF;
+          }
+        }
+    }
+    return frame_flags;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder * /*encoder*/) {
+    frame_flags_ &= ~(VP8_EFLAG_NO_UPD_LAST |
+                      VP8_EFLAG_NO_UPD_GF |
+                      VP8_EFLAG_NO_UPD_ARF);
+    // For temporal layer case.
+    if (cfg_.ts_number_layers > 1) {
+      frame_flags_ = SetFrameFlags(video->frame(),
+                                   cfg_.ts_number_layers,
+                                   pattern_switch_);
+      for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+        if (droppable_frames_[i] == video->frame()) {
+          std::cout << "Encoding droppable frame: "
+                    << droppable_frames_[i] << "\n";
+        }
+      }
+    } else {
+       if (droppable_nframes_ > 0 &&
+         (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+         for (unsigned int i = 0; i < droppable_nframes_; ++i) {
+           if (droppable_frames_[i] == video->frame()) {
+             std::cout << "Encoding droppable frame: "
+                       << droppable_frames_[i] << "\n";
+             frame_flags_ |= (VP8_EFLAG_NO_UPD_LAST |
+                              VP8_EFLAG_NO_UPD_GF |
+                              VP8_EFLAG_NO_UPD_ARF);
+             return;
+           }
+         }
+       }
+    }
+  }
+
+  double GetAveragePsnr() const {
+    if (nframes_)
+      return psnr_ / nframes_;
+    return 0.0;
+  }
+
+  double GetAverageMismatchPsnr() const {
+    if (mismatch_nframes_)
+      return mismatch_psnr_ / mismatch_nframes_;
+    return 0.0;
+  }
+
+  virtual bool DoDecode() const {
+    if (error_nframes_ > 0 &&
+        (cfg_.g_pass == VPX_RC_LAST_PASS || cfg_.g_pass == VPX_RC_ONE_PASS)) {
+      for (unsigned int i = 0; i < error_nframes_; ++i) {
+        if (error_frames_[i] == nframes_ - 1) {
+          std::cout << "             Skipping decoding frame: "
+                    << error_frames_[i] << "\n";
+          return 0;
+        }
+      }
+    }
+    return 1;
+  }
+
+  virtual void MismatchHook(const vpx_image_t *img1,
+                            const vpx_image_t *img2) {
+    double mismatch_psnr = compute_psnr(img1, img2);
+    mismatch_psnr_ += mismatch_psnr;
+    ++mismatch_nframes_;
+    // std::cout << "Mismatch frame psnr: " << mismatch_psnr << "\n";
+  }
+
+  void SetErrorFrames(int num, unsigned int *list) {
+    if (num > kMaxErrorFrames)
+      num = kMaxErrorFrames;
+    else if (num < 0)
+      num = 0;
+    error_nframes_ = num;
+    for (unsigned int i = 0; i < error_nframes_; ++i)
+      error_frames_[i] = list[i];
+  }
+
+  void SetDroppableFrames(int num, unsigned int *list) {
+    if (num > kMaxDroppableFrames)
+      num = kMaxDroppableFrames;
+    else if (num < 0)
+      num = 0;
+    droppable_nframes_ = num;
+    for (unsigned int i = 0; i < droppable_nframes_; ++i)
+      droppable_frames_[i] = list[i];
+  }
+
+  unsigned int GetMismatchFrames() {
+    return mismatch_nframes_;
+  }
+
+  void SetPatternSwitch(int frame_switch) {
+     pattern_switch_ = frame_switch;
+   }
+
+  bool svc_support_;
+
+ private:
+  double psnr_;
+  unsigned int nframes_;
+  unsigned int error_nframes_;
+  unsigned int droppable_nframes_;
+  unsigned int pattern_switch_;
+  double mismatch_psnr_;
+  unsigned int mismatch_nframes_;
+  unsigned int error_frames_[kMaxErrorFrames];
+  unsigned int droppable_frames_[kMaxDroppableFrames];
+  libvpx_test::TestMode encoding_mode_;
+};
+
+TEST_P(ErrorResilienceTestLarge, OnVersusOff) {
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 2000;
+  cfg_.g_lag_in_frames = 10;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 30);
+
+  // Error resilient mode OFF.
+  cfg_.g_error_resilient = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  const double psnr_resilience_off = GetAveragePsnr();
+  EXPECT_GT(psnr_resilience_off, 25.0);
+
+  // Error resilient mode ON.
+  cfg_.g_error_resilient = 1;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  const double psnr_resilience_on = GetAveragePsnr();
+  EXPECT_GT(psnr_resilience_on, 25.0);
+
+  // Test that turning on error resilient mode hurts by 10% at most.
+  if (psnr_resilience_off > 0.0) {
+    const double psnr_ratio = psnr_resilience_on / psnr_resilience_off;
+    EXPECT_GE(psnr_ratio, 0.9);
+    EXPECT_LE(psnr_ratio, 1.1);
+  }
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// if we lose (i.e., drop before decoding) a set of droppable
+// frames (i.e., frames that don't update any reference buffers).
+// Check both isolated and consecutive loss.
+TEST_P(ErrorResilienceTestLarge, DropFramesWithoutRecovery) {
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 500;
+  // FIXME(debargha): Fix this to work for any lag.
+  // Currently this test only works for lag = 0
+  cfg_.g_lag_in_frames = 0;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 40);
+
+  // Error resilient mode ON.
+  cfg_.g_error_resilient = 1;
+  cfg_.kf_mode = VPX_KF_DISABLED;
+
+  // Set an arbitrary set of error frames same as droppable frames.
+  // In addition to isolated loss/drop, add a long consecutive series
+  // (of size 9) of dropped frames.
+  unsigned int num_droppable_frames = 11;
+  unsigned int droppable_frame_list[] = {5, 16, 22, 23, 24, 25, 26, 27, 28,
+                                         29, 30};
+  SetDroppableFrames(num_droppable_frames, droppable_frame_list);
+  SetErrorFrames(num_droppable_frames, droppable_frame_list);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  // Test that no mismatches have been found
+  std::cout << "             Mismatch frames: "
+            << GetMismatchFrames() << "\n";
+  EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
+
+  // Reset previously set of error/droppable frames.
+  Reset();
+
+#if 0
+  // TODO(jkoleszar): This test is disabled for the time being as too
+  // sensitive. It's not clear how to set a reasonable threshold for
+  // this behavior.
+
+  // Now set an arbitrary set of error frames that are non-droppable
+  unsigned int num_error_frames = 3;
+  unsigned int error_frame_list[] = {3, 10, 20};
+  SetErrorFrames(num_error_frames, error_frame_list);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // Test that dropping an arbitrary set of inter frames does not hurt too much
+  // Note the Average Mismatch PSNR is the average of the PSNR between
+  // decoded frame and encoder's version of the same frame for all frames
+  // with mismatch.
+  const double psnr_resilience_mismatch = GetAverageMismatchPsnr();
+  std::cout << "             Mismatch PSNR: "
+            << psnr_resilience_mismatch << "\n";
+  EXPECT_GT(psnr_resilience_mismatch, 20.0);
+#endif
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// if we lose (i.e., drop before decoding) the enhancement layer frames for a
+// two layer temporal pattern. The base layer does not predict from the top
+// layer, so successful decoding is expected.
+TEST_P(ErrorResilienceTestLarge, 2LayersDropEnhancement) {
+  // This test doesn't run if SVC is not supported.
+  if (!svc_support_)
+    return;
+
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 500;
+  cfg_.g_lag_in_frames = 0;
+
+  cfg_.rc_end_usage = VPX_CBR;
+  // 2 Temporal layers, no spatial layers, CBR mode.
+  cfg_.ss_number_layers = 1;
+  cfg_.ts_number_layers = 2;
+  cfg_.ts_rate_decimator[0] = 2;
+  cfg_.ts_rate_decimator[1] = 1;
+  cfg_.ts_periodicity = 2;
+  cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+  cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 40);
+
+  // Error resilient mode ON.
+  cfg_.g_error_resilient = 1;
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  SetPatternSwitch(0);
+
+  // The odd frames are the enhancement layer for 2 layer pattern, so set
+  // those frames as droppable. Drop the last 7 frames.
+  unsigned int num_droppable_frames = 7;
+  unsigned int droppable_frame_list[] = {27, 29, 31, 33, 35, 37, 39};
+  SetDroppableFrames(num_droppable_frames, droppable_frame_list);
+  SetErrorFrames(num_droppable_frames, droppable_frame_list);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  // Test that no mismatches have been found
+  std::cout << "             Mismatch frames: "
+            << GetMismatchFrames() << "\n";
+  EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
+
+  // Reset previously set of error/droppable frames.
+  Reset();
+}
+
+// Check for successful decoding and no encoder/decoder mismatch
+// for a two layer temporal pattern, where at some point in the
+// sequence, the LAST ref is not used anymore.
+TEST_P(ErrorResilienceTestLarge, 2LayersNoRefLast) {
+  // This test doesn't run if SVC is not supported.
+  if (!svc_support_)
+    return;
+
+  const vpx_rational timebase = { 33333333, 1000000000 };
+  cfg_.g_timebase = timebase;
+  cfg_.rc_target_bitrate = 500;
+  cfg_.g_lag_in_frames = 0;
+
+  cfg_.rc_end_usage = VPX_CBR;
+  // 2 Temporal layers, no spatial layers, CBR mode.
+  cfg_.ss_number_layers = 1;
+  cfg_.ts_number_layers = 2;
+  cfg_.ts_rate_decimator[0] = 2;
+  cfg_.ts_rate_decimator[1] = 1;
+  cfg_.ts_periodicity = 2;
+  cfg_.ts_target_bitrate[0] = 60 * cfg_.rc_target_bitrate / 100;
+  cfg_.ts_target_bitrate[1] = cfg_.rc_target_bitrate;
+
+  init_flags_ = VPX_CODEC_USE_PSNR;
+
+  libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                     timebase.den, timebase.num, 0, 100);
+
+  // Error resilient mode ON.
+  cfg_.g_error_resilient = 1;
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  SetPatternSwitch(60);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  // Test that no mismatches have been found
+  std::cout << "             Mismatch frames: "
+            << GetMismatchFrames() << "\n";
+  EXPECT_EQ(GetMismatchFrames(), (unsigned int) 0);
+
+  // Reset previously set of error/droppable frames.
+  Reset();
+}
+
+class ErrorResilienceTestLargeCodecControls : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  ErrorResilienceTestLargeCodecControls()
+      : EncoderTest(GET_PARAM(0)),
+        encoding_mode_(GET_PARAM(1)) {
+    Reset();
+  }
+
+  virtual ~ErrorResilienceTestLargeCodecControls() {}
+
+  void Reset() {
+    last_pts_ = 0;
+    tot_frame_number_ = 0;
+    // For testing up to 3 layers.
+    for (int i = 0; i < 3; ++i) {
+      bits_total_[i] = 0;
+    }
+    duration_ = 0.0;
+  }
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+  }
+
+  //
+  // Frame flags and layer id for temporal layers.
+  //
+
+  // For two layers, test pattern is:
+  //   1     3
+  // 0    2     .....
+  // For three layers, test pattern is:
+  //   1      3    5      7
+  //      2           6
+  // 0          4            ....
+  // LAST is always update on base/layer 0, GOLDEN is updated on layer 1,
+  // and ALTREF is updated on top layer for 3 layer pattern.
+  int SetFrameFlags(int frame_num, int num_temp_layers) {
+    int frame_flags = 0;
+    if (num_temp_layers == 2) {
+      if (frame_num % 2 == 0) {
+        // Layer 0: predict from L and ARF, update L.
+        frame_flags = VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_UPD_GF |
+                      VP8_EFLAG_NO_UPD_ARF;
+      } else {
+        // Layer 1: predict from L, G and ARF, and update G.
+        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+                      VP8_EFLAG_NO_UPD_ENTROPY;
+      }
+    } else if (num_temp_layers == 3) {
+      if (frame_num % 4 == 0) {
+        // Layer 0: predict from L, update L.
+        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_ARF |
+                      VP8_EFLAG_NO_REF_GF | VP8_EFLAG_NO_REF_ARF;
+      } else if ((frame_num - 2) % 4 == 0) {
+        // Layer 1: predict from L, G,  update G.
+        frame_flags = VP8_EFLAG_NO_UPD_ARF | VP8_EFLAG_NO_UPD_LAST |
+                      VP8_EFLAG_NO_REF_ARF;
+      }  else if ((frame_num - 1) % 2 == 0) {
+        // Layer 2: predict from L, G, ARF; update ARG.
+        frame_flags = VP8_EFLAG_NO_UPD_GF | VP8_EFLAG_NO_UPD_LAST;
+      }
+    }
+    return frame_flags;
+  }
+
+  int SetLayerId(int frame_num, int num_temp_layers) {
+    int layer_id = 0;
+    if (num_temp_layers == 2) {
+      if (frame_num % 2 == 0) {
+        layer_id = 0;
+      } else {
+         layer_id = 1;
+      }
+    } else if (num_temp_layers == 3) {
+      if (frame_num % 4 == 0) {
+        layer_id = 0;
+      } else if ((frame_num - 2) % 4 == 0) {
+        layer_id = 1;
+      } else if ((frame_num - 1) % 2 == 0) {
+        layer_id = 2;
+      }
+    }
+    return layer_id;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (cfg_.ts_number_layers > 1) {
+        int layer_id = SetLayerId(video->frame(), cfg_.ts_number_layers);
+        int frame_flags = SetFrameFlags(video->frame(), cfg_.ts_number_layers);
+        if (video->frame() > 0) {
+          encoder->Control(VP8E_SET_TEMPORAL_LAYER_ID, layer_id);
+          encoder->Control(VP8E_SET_FRAME_FLAGS, frame_flags);
+        }
+       const vpx_rational_t tb = video->timebase();
+       timebase_ = static_cast<double>(tb.num) / tb.den;
+       duration_ = 0;
+       return;
+    }
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    // Time since last timestamp = duration.
+    vpx_codec_pts_t duration = pkt->data.frame.pts - last_pts_;
+    if (duration > 1) {
+      // Update counter for total number of frames (#frames input to encoder).
+      // Needed for setting the proper layer_id below.
+      tot_frame_number_ += static_cast<int>(duration - 1);
+    }
+    int layer = SetLayerId(tot_frame_number_, cfg_.ts_number_layers);
+    const size_t frame_size_in_bits = pkt->data.frame.sz * 8;
+    // Update the total encoded bits. For temporal layers, update the cumulative
+    // encoded bits per layer.
+    for (int i = layer; i < static_cast<int>(cfg_.ts_number_layers); ++i) {
+      bits_total_[i] += frame_size_in_bits;
+    }
+    // Update the most recent pts.
+    last_pts_ = pkt->data.frame.pts;
+    ++tot_frame_number_;
+  }
+
+  virtual void EndPassHook(void) {
+    duration_ = (last_pts_ + 1) * timebase_;
+    if (cfg_.ts_number_layers  > 1) {
+      for (int layer = 0; layer < static_cast<int>(cfg_.ts_number_layers);
+          ++layer) {
+        if (bits_total_[layer]) {
+          // Effective file datarate:
+          effective_datarate_[layer] = (bits_total_[layer] / 1000.0) / duration_;
+        }
+      }
+    }
+  }
+
+  double effective_datarate_[3];
+   private:
+    libvpx_test::TestMode encoding_mode_;
+    vpx_codec_pts_t last_pts_;
+    double timebase_;
+    int64_t bits_total_[3];
+    double duration_;
+    int tot_frame_number_;
+  };
+
+// Check two codec controls used for:
+// (1) for setting temporal layer id, and (2) for settings encoder flags.
+// This test invokes those controls for each frame, and verifies encoder/decoder
+// mismatch and basic rate control response.
+// TODO(marpan): Maybe move this test to datarate_test.cc.
+TEST_P(ErrorResilienceTestLargeCodecControls, CodecControl3TemporalLayers) {
+  cfg_.rc_buf_initial_sz = 500;
+  cfg_.rc_buf_optimal_sz = 500;
+  cfg_.rc_buf_sz = 1000;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.rc_min_quantizer = 2;
+  cfg_.rc_max_quantizer = 56;
+  cfg_.rc_end_usage = VPX_CBR;
+  cfg_.rc_dropframe_thresh = 1;
+  cfg_.g_lag_in_frames = 0;
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  cfg_.g_error_resilient = 1;
+
+  // 3 Temporal layers. Framerate decimation (4, 2, 1).
+  cfg_.ts_number_layers = 3;
+  cfg_.ts_rate_decimator[0] = 4;
+  cfg_.ts_rate_decimator[1] = 2;
+  cfg_.ts_rate_decimator[2] = 1;
+  cfg_.ts_periodicity = 4;
+  cfg_.ts_layer_id[0] = 0;
+  cfg_.ts_layer_id[1] = 2;
+  cfg_.ts_layer_id[2] = 1;
+  cfg_.ts_layer_id[3] = 2;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 200);
+  for (int i = 200; i <= 800; i += 200) {
+    cfg_.rc_target_bitrate = i;
+    Reset();
+    // 40-20-40 bitrate allocation for 3 temporal layers.
+    cfg_.ts_target_bitrate[0] = 40 * cfg_.rc_target_bitrate / 100;
+    cfg_.ts_target_bitrate[1] = 60 * cfg_.rc_target_bitrate / 100;
+    cfg_.ts_target_bitrate[2] = cfg_.rc_target_bitrate;
+    ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+    for (int j = 0; j < static_cast<int>(cfg_.ts_number_layers); ++j) {
+      ASSERT_GE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 0.75)
+          << " The datarate for the file is lower than target by too much, "
+              "for layer: " << j;
+      ASSERT_LE(effective_datarate_[j], cfg_.ts_target_bitrate[j] * 1.25)
+          << " The datarate for the file is greater than target by too much, "
+              "for layer: " << j;
+    }
+  }
+}
+
+VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
+                          ::testing::Values(true));
+VP8_INSTANTIATE_TEST_CASE(ErrorResilienceTestLargeCodecControls,
+                          ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
+                          ::testing::Values(true));
+// SVC-related tests don't run for VP10 since SVC is not supported.
+VP10_INSTANTIATE_TEST_CASE(ErrorResilienceTestLarge, ONE_PASS_TEST_MODES,
+                           ::testing::Values(false));
+}  // namespace
diff --git a/src/third_party/libvpx/test/examples.sh b/src/third_party/libvpx/test/examples.sh
new file mode 100755
index 0000000..39f7e39
--- /dev/null
+++ b/src/third_party/libvpx/test/examples.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file runs all of the tests for the libvpx examples.
+##
+. $(dirname $0)/tools_common.sh
+
+example_tests=$(ls $(dirname $0)/*.sh)
+
+# List of script names to exclude.
+exclude_list="examples tools_common"
+
+# Filter out the scripts in $exclude_list.
+for word in ${exclude_list}; do
+  example_tests=$(filter_strings "${example_tests}" "${word}" exclude)
+done
+
+for test in ${example_tests}; do
+  # Source each test script so that exporting variables can be avoided.
+  VPX_TEST_NAME="$(basename ${test%.*})"
+  . "${test}"
+done
diff --git a/src/third_party/libvpx/test/external_frame_buffer_test.cc b/src/third_party/libvpx/test/external_frame_buffer_test.cc
new file mode 100644
index 0000000..2570f44
--- /dev/null
+++ b/src/third_party/libvpx/test/external_frame_buffer_test.cc
@@ -0,0 +1,493 @@
+/*
+ *  Copyright (c) 2014 The WebM 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>
+
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+
+namespace {
+
+const int kVideoNameParam = 1;
+
+struct ExternalFrameBuffer {
+  uint8_t *data;
+  size_t size;
+  int in_use;
+};
+
+// Class to manipulate a list of external frame buffers.
+class ExternalFrameBufferList {
+ public:
+  ExternalFrameBufferList()
+      : num_buffers_(0),
+        ext_fb_list_(NULL) {}
+
+  virtual ~ExternalFrameBufferList() {
+    for (int i = 0; i < num_buffers_; ++i) {
+      delete [] ext_fb_list_[i].data;
+    }
+    delete [] ext_fb_list_;
+  }
+
+  // Creates the list to hold the external buffers. Returns true on success.
+  bool CreateBufferList(int num_buffers) {
+    if (num_buffers < 0)
+      return false;
+
+    num_buffers_ = num_buffers;
+    ext_fb_list_ = new ExternalFrameBuffer[num_buffers_];
+    EXPECT_TRUE(ext_fb_list_ != NULL);
+    memset(ext_fb_list_, 0, sizeof(ext_fb_list_[0]) * num_buffers_);
+    return true;
+  }
+
+  // Searches the frame buffer list for a free frame buffer. Makes sure
+  // that the frame buffer is at least |min_size| in bytes. Marks that the
+  // frame buffer is in use by libvpx. Finally sets |fb| to point to the
+  // external frame buffer. Returns < 0 on an error.
+  int GetFreeFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
+    EXPECT_TRUE(fb != NULL);
+    const int idx = FindFreeBufferIndex();
+    if (idx == num_buffers_)
+      return -1;
+
+    if (ext_fb_list_[idx].size < min_size) {
+      delete [] ext_fb_list_[idx].data;
+      ext_fb_list_[idx].data = new uint8_t[min_size];
+      memset(ext_fb_list_[idx].data, 0, min_size);
+      ext_fb_list_[idx].size = min_size;
+    }
+
+    SetFrameBuffer(idx, fb);
+    return 0;
+  }
+
+  // Test function that will not allocate any data for the frame buffer.
+  // Returns < 0 on an error.
+  int GetZeroFrameBuffer(size_t min_size, vpx_codec_frame_buffer_t *fb) {
+    EXPECT_TRUE(fb != NULL);
+    const int idx = FindFreeBufferIndex();
+    if (idx == num_buffers_)
+      return -1;
+
+    if (ext_fb_list_[idx].size < min_size) {
+      delete [] ext_fb_list_[idx].data;
+      ext_fb_list_[idx].data = NULL;
+      ext_fb_list_[idx].size = min_size;
+    }
+
+    SetFrameBuffer(idx, fb);
+    return 0;
+  }
+
+  // Marks the external frame buffer that |fb| is pointing to as free.
+  // Returns < 0 on an error.
+  int ReturnFrameBuffer(vpx_codec_frame_buffer_t *fb) {
+    if (fb == NULL) {
+      EXPECT_TRUE(fb != NULL);
+      return -1;
+    }
+    ExternalFrameBuffer *const ext_fb =
+        reinterpret_cast<ExternalFrameBuffer*>(fb->priv);
+    if (ext_fb == NULL) {
+      EXPECT_TRUE(ext_fb != NULL);
+      return -1;
+    }
+    EXPECT_EQ(1, ext_fb->in_use);
+    ext_fb->in_use = 0;
+    return 0;
+  }
+
+  // Checks that the ximage data is contained within the external frame buffer
+  // private data passed back in the ximage.
+  void CheckXImageFrameBuffer(const vpx_image_t *img) {
+    if (img->fb_priv != NULL) {
+      const struct ExternalFrameBuffer *const ext_fb =
+          reinterpret_cast<ExternalFrameBuffer*>(img->fb_priv);
+
+      ASSERT_TRUE(img->planes[0] >= ext_fb->data &&
+                  img->planes[0] < (ext_fb->data + ext_fb->size));
+    }
+  }
+
+ private:
+  // Returns the index of the first free frame buffer. Returns |num_buffers_|
+  // if there are no free frame buffers.
+  int FindFreeBufferIndex() {
+    int i;
+    // Find a free frame buffer.
+    for (i = 0; i < num_buffers_; ++i) {
+      if (!ext_fb_list_[i].in_use)
+        break;
+    }
+    return i;
+  }
+
+  // Sets |fb| to an external frame buffer. idx is the index into the frame
+  // buffer list.
+  void SetFrameBuffer(int idx, vpx_codec_frame_buffer_t *fb) {
+    ASSERT_TRUE(fb != NULL);
+    fb->data = ext_fb_list_[idx].data;
+    fb->size = ext_fb_list_[idx].size;
+    ASSERT_EQ(0, ext_fb_list_[idx].in_use);
+    ext_fb_list_[idx].in_use = 1;
+    fb->priv = &ext_fb_list_[idx];
+  }
+
+  int num_buffers_;
+  ExternalFrameBuffer *ext_fb_list_;
+};
+
+#if CONFIG_WEBM_IO
+
+// Callback used by libvpx to request the application to return a frame
+// buffer of at least |min_size| in bytes.
+int get_vp9_frame_buffer(void *user_priv, size_t min_size,
+                         vpx_codec_frame_buffer_t *fb) {
+  ExternalFrameBufferList *const fb_list =
+      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
+  return fb_list->GetFreeFrameBuffer(min_size, fb);
+}
+
+// Callback used by libvpx to tell the application that |fb| is not needed
+// anymore.
+int release_vp9_frame_buffer(void *user_priv,
+                             vpx_codec_frame_buffer_t *fb) {
+  ExternalFrameBufferList *const fb_list =
+      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
+  return fb_list->ReturnFrameBuffer(fb);
+}
+
+// Callback will not allocate data for frame buffer.
+int get_vp9_zero_frame_buffer(void *user_priv, size_t min_size,
+                              vpx_codec_frame_buffer_t *fb) {
+  ExternalFrameBufferList *const fb_list =
+      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
+  return fb_list->GetZeroFrameBuffer(min_size, fb);
+}
+
+// Callback will allocate one less byte than |min_size|.
+int get_vp9_one_less_byte_frame_buffer(void *user_priv, size_t min_size,
+                                       vpx_codec_frame_buffer_t *fb) {
+  ExternalFrameBufferList *const fb_list =
+      reinterpret_cast<ExternalFrameBufferList*>(user_priv);
+  return fb_list->GetFreeFrameBuffer(min_size - 1, fb);
+}
+
+// Callback will not release the external frame buffer.
+int do_not_release_vp9_frame_buffer(void *user_priv,
+                                    vpx_codec_frame_buffer_t *fb) {
+  (void)user_priv;
+  (void)fb;
+  return 0;
+}
+
+#endif  // CONFIG_WEBM_IO
+
+// Class for testing passing in external frame buffers to libvpx.
+class ExternalFrameBufferMD5Test
+    : public ::libvpx_test::DecoderTest,
+      public ::libvpx_test::CodecTestWithParam<const char*> {
+ protected:
+  ExternalFrameBufferMD5Test()
+      : DecoderTest(GET_PARAM(::libvpx_test::kCodecFactoryParam)),
+        md5_file_(NULL),
+        num_buffers_(0) {}
+
+  virtual ~ExternalFrameBufferMD5Test() {
+    if (md5_file_ != NULL)
+      fclose(md5_file_);
+  }
+
+  virtual void PreDecodeFrameHook(
+      const libvpx_test::CompressedVideoSource &video,
+      libvpx_test::Decoder *decoder) {
+    if (num_buffers_ > 0 && video.frame_number() == 0) {
+      // Have libvpx use frame buffers we create.
+      ASSERT_TRUE(fb_list_.CreateBufferList(num_buffers_));
+      ASSERT_EQ(VPX_CODEC_OK,
+                decoder->SetFrameBufferFunctions(
+                    GetVP9FrameBuffer, ReleaseVP9FrameBuffer, this));
+    }
+  }
+
+  void OpenMD5File(const std::string &md5_file_name_) {
+    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+    ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
+        << md5_file_name_;
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t &img,
+                                     const unsigned int frame_number) {
+    ASSERT_TRUE(md5_file_ != NULL);
+    char expected_md5[33];
+    char junk[128];
+
+    // Read correct md5 checksums.
+    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
+    ASSERT_NE(EOF, res) << "Read md5 data failed";
+    expected_md5[32] = '\0';
+
+    ::libvpx_test::MD5 md5_res;
+    md5_res.Add(&img);
+    const char *const actual_md5 = md5_res.Get();
+
+    // Check md5 match.
+    ASSERT_STREQ(expected_md5, actual_md5)
+        << "Md5 checksums don't match: frame number = " << frame_number;
+  }
+
+  // Callback to get a free external frame buffer. Return value < 0 is an
+  // error.
+  static int GetVP9FrameBuffer(void *user_priv, size_t min_size,
+                               vpx_codec_frame_buffer_t *fb) {
+    ExternalFrameBufferMD5Test *const md5Test =
+        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
+    return md5Test->fb_list_.GetFreeFrameBuffer(min_size, fb);
+  }
+
+  // Callback to release an external frame buffer. Return value < 0 is an
+  // error.
+  static int ReleaseVP9FrameBuffer(void *user_priv,
+                                   vpx_codec_frame_buffer_t *fb) {
+    ExternalFrameBufferMD5Test *const md5Test =
+        reinterpret_cast<ExternalFrameBufferMD5Test*>(user_priv);
+    return md5Test->fb_list_.ReturnFrameBuffer(fb);
+  }
+
+  void set_num_buffers(int num_buffers) { num_buffers_ = num_buffers; }
+  int num_buffers() const { return num_buffers_; }
+
+ private:
+  FILE *md5_file_;
+  int num_buffers_;
+  ExternalFrameBufferList fb_list_;
+};
+
+#if CONFIG_WEBM_IO
+const char kVP9TestFile[] = "vp90-2-02-size-lf-1920x1080.webm";
+
+// Class for testing passing in external frame buffers to libvpx.
+class ExternalFrameBufferTest : public ::testing::Test {
+ protected:
+  ExternalFrameBufferTest()
+      : video_(NULL),
+        decoder_(NULL),
+        num_buffers_(0) {}
+
+  virtual void SetUp() {
+    video_ = new libvpx_test::WebMVideoSource(kVP9TestFile);
+    ASSERT_TRUE(video_ != NULL);
+    video_->Init();
+    video_->Begin();
+
+    vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+    decoder_ = new libvpx_test::VP9Decoder(cfg, 0);
+    ASSERT_TRUE(decoder_ != NULL);
+  }
+
+  virtual void TearDown() {
+    delete decoder_;
+    delete video_;
+  }
+
+  // Passes the external frame buffer information to libvpx.
+  vpx_codec_err_t SetFrameBufferFunctions(
+      int num_buffers,
+      vpx_get_frame_buffer_cb_fn_t cb_get,
+      vpx_release_frame_buffer_cb_fn_t cb_release) {
+    if (num_buffers > 0) {
+      num_buffers_ = num_buffers;
+      EXPECT_TRUE(fb_list_.CreateBufferList(num_buffers_));
+    }
+
+    return decoder_->SetFrameBufferFunctions(cb_get, cb_release, &fb_list_);
+  }
+
+  vpx_codec_err_t DecodeOneFrame() {
+    const vpx_codec_err_t res =
+        decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+    CheckDecodedFrames();
+    if (res == VPX_CODEC_OK)
+      video_->Next();
+    return res;
+  }
+
+  vpx_codec_err_t DecodeRemainingFrames() {
+    for (; video_->cxdata() != NULL; video_->Next()) {
+      const vpx_codec_err_t res =
+          decoder_->DecodeFrame(video_->cxdata(), video_->frame_size());
+      if (res != VPX_CODEC_OK)
+        return res;
+      CheckDecodedFrames();
+    }
+    return VPX_CODEC_OK;
+  }
+
+ private:
+  void CheckDecodedFrames() {
+    libvpx_test::DxDataIterator dec_iter = decoder_->GetDxData();
+    const vpx_image_t *img = NULL;
+
+    // Get decompressed data
+    while ((img = dec_iter.Next()) != NULL) {
+      fb_list_.CheckXImageFrameBuffer(img);
+    }
+  }
+
+  libvpx_test::WebMVideoSource *video_;
+  libvpx_test::VP9Decoder *decoder_;
+  int num_buffers_;
+  ExternalFrameBufferList fb_list_;
+};
+#endif  // CONFIG_WEBM_IO
+
+// This test runs through the set of test vectors, and decodes them.
+// Libvpx will call into the application to allocate a frame buffer when
+// needed. The md5 checksums are computed for each frame in the video file.
+// If md5 checksums match the correct md5 data, then the test is passed.
+// Otherwise, the test failed.
+TEST_P(ExternalFrameBufferMD5Test, ExtFBMD5Match) {
+  const std::string filename = GET_PARAM(kVideoNameParam);
+  libvpx_test::CompressedVideoSource *video = NULL;
+
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + four jitter buffers.
+  const int jitter_buffers = 4;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  set_num_buffers(num_buffers);
+
+#if CONFIG_VP8_DECODER
+  // Tell compiler we are not using kVP8TestVectors.
+  (void)libvpx_test::kVP8TestVectors;
+#endif
+
+  // Open compressed video file.
+  if (filename.substr(filename.length() - 3, 3) == "ivf") {
+    video = new libvpx_test::IVFVideoSource(filename);
+  } else {
+#if CONFIG_WEBM_IO
+    video = new libvpx_test::WebMVideoSource(filename);
+#else
+    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+            filename.c_str());
+    return;
+#endif
+  }
+  ASSERT_TRUE(video != NULL);
+  video->Init();
+
+  // Construct md5 file name.
+  const std::string md5_filename = filename + ".md5";
+  OpenMD5File(md5_filename);
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video));
+  delete video;
+}
+
+#if CONFIG_WEBM_IO
+TEST_F(ExternalFrameBufferTest, MinFrameBuffers) {
+  // Minimum number of external frame buffers for VP9 is
+  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS.
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(
+                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, EightJitterBuffers) {
+  // Number of buffers equals #VP9_MAXIMUM_REF_BUFFERS +
+  // #VPX_MAXIMUM_WORK_BUFFERS + eight jitter buffers.
+  const int jitter_buffers = 8;
+  const int num_buffers =
+      VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS + jitter_buffers;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(
+                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NotEnoughBuffers) {
+  // Minimum number of external frame buffers for VP9 is
+  // #VP9_MAXIMUM_REF_BUFFERS + #VPX_MAXIMUM_WORK_BUFFERS. Most files will
+  // only use 5 frame buffers at one time.
+  const int num_buffers = 2;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(
+                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NoRelease) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer,
+                                    do_not_release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeRemainingFrames());
+}
+
+TEST_F(ExternalFrameBufferTest, NullRealloc) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(num_buffers, get_vp9_zero_frame_buffer,
+                                    release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+TEST_F(ExternalFrameBufferTest, ReallocOneLessByte) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK,
+            SetFrameBufferFunctions(
+                num_buffers, get_vp9_one_less_byte_frame_buffer,
+                release_vp9_frame_buffer));
+  ASSERT_EQ(VPX_CODEC_MEM_ERROR, DecodeOneFrame());
+}
+
+TEST_F(ExternalFrameBufferTest, NullGetFunction) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetFrameBufferFunctions(num_buffers, NULL,
+                                    release_vp9_frame_buffer));
+}
+
+TEST_F(ExternalFrameBufferTest, NullReleaseFunction) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_INVALID_PARAM,
+            SetFrameBufferFunctions(num_buffers, get_vp9_frame_buffer, NULL));
+}
+
+TEST_F(ExternalFrameBufferTest, SetAfterDecode) {
+  const int num_buffers = VP9_MAXIMUM_REF_BUFFERS + VPX_MAXIMUM_WORK_BUFFERS;
+  ASSERT_EQ(VPX_CODEC_OK, DecodeOneFrame());
+  ASSERT_EQ(VPX_CODEC_ERROR,
+            SetFrameBufferFunctions(
+                num_buffers, get_vp9_frame_buffer, release_vp9_frame_buffer));
+}
+#endif  // CONFIG_WEBM_IO
+
+VP9_INSTANTIATE_TEST_CASE(ExternalFrameBufferMD5Test,
+                          ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+                                              libvpx_test::kVP9TestVectors +
+                                              libvpx_test::kNumVP9TestVectors));
+}  // namespace
diff --git a/src/third_party/libvpx/test/fdct4x4_test.cc b/src/third_party/libvpx/test/fdct4x4_test.cc
new file mode 100644
index 0000000..735cccf
--- /dev/null
+++ b/src/third_party/libvpx/test/fdct4x4_test.cc
@@ -0,0 +1,546 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+const int kNumCoeffs = 16;
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+                        int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+                        int tx_type);
+
+typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct4x4Param;
+typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht4x4Param;
+
+void fdct4x4_ref(const int16_t *in, tran_low_t *out, int stride,
+                 int /*tx_type*/) {
+  vpx_fdct4x4_c(in, out, stride);
+}
+
+void fht4x4_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
+  vp9_fht4x4_c(in, out, stride, tx_type);
+}
+
+void fwht4x4_ref(const int16_t *in, tran_low_t *out, int stride,
+                 int /*tx_type*/) {
+  vp9_fwht4x4_c(in, out, stride);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct4x4_16_add_c(in, out, stride, 10);
+}
+
+void idct4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct4x4_16_add_c(in, out, stride, 12);
+}
+
+void iht4x4_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 10);
+}
+
+void iht4x4_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht4x4_16_add_c(in, out, stride, tx_type, 12);
+}
+
+void iwht4x4_10(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_iwht4x4_16_add_c(in, out, stride, 10);
+}
+
+void iwht4x4_12(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_iwht4x4_16_add_c(in, out, stride, 12);
+}
+
+#if HAVE_SSE2
+void idct4x4_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 10);
+}
+
+void idct4x4_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct4x4_16_add_sse2(in, out, stride, 12);
+}
+#endif  // HAVE_SSE2
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+class Trans4x4TestBase {
+ public:
+  virtual ~Trans4x4TestBase() {}
+
+ protected:
+  virtual void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) = 0;
+
+  virtual void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) = 0;
+
+  void RunAccuracyCheck(int limit) {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    uint32_t max_error = 0;
+    int64_t total_error = 0;
+    const int count_test_block = 10000;
+    for (int i = 0; i < count_test_block; ++i) {
+      DECLARE_ALIGNED(16, int16_t, test_input_block[kNumCoeffs]);
+      DECLARE_ALIGNED(16, tran_low_t, test_temp_block[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+      DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+      DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+      // Initialize a test block with input range [-255, 255].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8();
+          dst[j] = rnd.Rand8();
+          test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand16() & mask_;
+          dst16[j] = rnd.Rand16() & mask_;
+          test_input_block[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(test_input_block,
+                                          test_temp_block, pitch_));
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(test_temp_block,
+                                            CONVERT_TO_BYTEPTR(dst16), pitch_));
+#endif
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        ASSERT_EQ(VPX_BITS_8, bit_depth_);
+        const int diff = dst[j] - src[j];
+#endif
+        const uint32_t error = diff * diff;
+        if (max_error < error)
+          max_error = error;
+        total_error += error;
+      }
+    }
+
+    EXPECT_GE(static_cast<uint32_t>(limit), max_error)
+        << "Error: 4x4 FHT/IHT has an individual round trip error > "
+        << limit;
+
+    EXPECT_GE(count_test_block * limit, total_error)
+        << "Error: 4x4 FHT/IHT has average round trip error > " << limit
+        << " per block";
+  }
+
+  void RunCoeffCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 5000;
+    DECLARE_ALIGNED(16, int16_t, input_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j)
+        input_block[j] = (rnd.Rand16() & mask_) - (rnd.Rand16() & mask_);
+
+      fwd_txfm_ref(input_block, output_ref_block, pitch_, tx_type_);
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_block, output_block, pitch_));
+
+      // The minimum quant value is 4.
+      for (int j = 0; j < kNumCoeffs; ++j)
+        EXPECT_EQ(output_block[j], output_ref_block[j]);
+    }
+  }
+
+  void RunMemCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 5000;
+    DECLARE_ALIGNED(16, int16_t, input_extreme_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, output_block[kNumCoeffs]);
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        input_extreme_block[j] = rnd.Rand8() % 2 ? mask_ : -mask_;
+      }
+      if (i == 0) {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = mask_;
+      } else if (i == 1) {
+        for (int j = 0; j < kNumCoeffs; ++j)
+          input_extreme_block[j] = -mask_;
+      }
+
+      fwd_txfm_ref(input_extreme_block, output_ref_block, pitch_, tx_type_);
+      ASM_REGISTER_STATE_CHECK(RunFwdTxfm(input_extreme_block,
+                                          output_block, pitch_));
+
+      // The minimum quant value is 4.
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        EXPECT_EQ(output_block[j], output_ref_block[j]);
+        EXPECT_GE(4 * DCT_MAX_VALUE << (bit_depth_ - 8), abs(output_block[j]))
+            << "Error: 4x4 FDCT has coefficient larger than 4*DCT_MAX_VALUE";
+      }
+    }
+  }
+
+  void RunInvAccuracyCheck(int limit) {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+#endif
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8();
+          dst[j] = rnd.Rand8();
+          in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand16() & mask_;
+          dst16[j] = rnd.Rand16() & mask_;
+          in[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      fwd_txfm_ref(in, coeff, pitch_, tx_type_);
+
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
+                                            pitch_));
+#endif
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const int diff = dst[j] - src[j];
+#endif
+        const uint32_t error = diff * diff;
+        EXPECT_GE(static_cast<uint32_t>(limit), error)
+            << "Error: 4x4 IDCT has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+
+  int pitch_;
+  int tx_type_;
+  FhtFunc fwd_txfm_ref;
+  vpx_bit_depth_t bit_depth_;
+  int mask_;
+};
+
+class Trans4x4DCT
+    : public Trans4x4TestBase,
+      public ::testing::TestWithParam<Dct4x4Param> {
+ public:
+  virtual ~Trans4x4DCT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    pitch_    = 4;
+    fwd_txfm_ref = fdct4x4_ref;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride);
+  }
+  void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+
+  FdctFunc fwd_txfm_;
+  IdctFunc inv_txfm_;
+};
+
+TEST_P(Trans4x4DCT, AccuracyCheck) {
+  RunAccuracyCheck(1);
+}
+
+TEST_P(Trans4x4DCT, CoeffCheck) {
+  RunCoeffCheck();
+}
+
+TEST_P(Trans4x4DCT, MemCheck) {
+  RunMemCheck();
+}
+
+TEST_P(Trans4x4DCT, InvAccuracyCheck) {
+  RunInvAccuracyCheck(1);
+}
+
+class Trans4x4HT
+    : public Trans4x4TestBase,
+      public ::testing::TestWithParam<Ht4x4Param> {
+ public:
+  virtual ~Trans4x4HT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    pitch_    = 4;
+    fwd_txfm_ref = fht4x4_ref;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride, tx_type_);
+  }
+
+  void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride, tx_type_);
+  }
+
+  FhtFunc fwd_txfm_;
+  IhtFunc inv_txfm_;
+};
+
+TEST_P(Trans4x4HT, AccuracyCheck) {
+  RunAccuracyCheck(1);
+}
+
+TEST_P(Trans4x4HT, CoeffCheck) {
+  RunCoeffCheck();
+}
+
+TEST_P(Trans4x4HT, MemCheck) {
+  RunMemCheck();
+}
+
+TEST_P(Trans4x4HT, InvAccuracyCheck) {
+  RunInvAccuracyCheck(1);
+}
+
+class Trans4x4WHT
+    : public Trans4x4TestBase,
+      public ::testing::TestWithParam<Dct4x4Param> {
+ public:
+  virtual ~Trans4x4WHT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    pitch_    = 4;
+    fwd_txfm_ref = fwht4x4_ref;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(const int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride);
+  }
+  void RunInvTxfm(const tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+
+  FdctFunc fwd_txfm_;
+  IdctFunc inv_txfm_;
+};
+
+TEST_P(Trans4x4WHT, AccuracyCheck) {
+  RunAccuracyCheck(0);
+}
+
+TEST_P(Trans4x4WHT, CoeffCheck) {
+  RunCoeffCheck();
+}
+
+TEST_P(Trans4x4WHT, MemCheck) {
+  RunMemCheck();
+}
+
+TEST_P(Trans4x4WHT, InvAccuracyCheck) {
+  RunInvAccuracyCheck(0);
+}
+using std::tr1::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct4x4_c, &idct4x4_12, 0, VPX_BITS_12),
+        make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct4x4_c, &vpx_idct4x4_16_add_c, 0, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 0, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 1, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 2, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_10, 3, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 0, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 1, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 2, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht4x4_c, &iht4x4_12, 3, VPX_BITS_12),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4WHT,
+    ::testing::Values(
+        make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_10, 0, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fwht4x4_c, &iwht4x4_12, 0, VPX_BITS_12),
+        make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, Trans4x4WHT,
+    ::testing::Values(
+        make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct4x4_c,
+                   &vpx_idct4x4_16_add_neon, 0, VPX_BITS_8)));
+#endif  // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_c, &vp9_iht4x4_16_add_neon, 3, VPX_BITS_8)));
+#endif  // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if CONFIG_USE_X86INC && HAVE_SSE2 && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans4x4WHT,
+    ::testing::Values(
+        make_tuple(&vp9_fwht4x4_sse2, &vpx_iwht4x4_16_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fwht4x4_c, &vpx_iwht4x4_16_add_sse2, 0, VPX_BITS_8)));
+#endif
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct4x4_sse2,
+                   &vpx_idct4x4_16_add_sse2, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_sse2, 3, VPX_BITS_8)));
+#endif  // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_fdct4x4_c,    &idct4x4_10_sse2, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_10_sse2, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct4x4_c,    &idct4x4_12_sse2, 0, VPX_BITS_12),
+        make_tuple(&vpx_highbd_fdct4x4_sse2, &idct4x4_12_sse2, 0, VPX_BITS_12),
+        make_tuple(&vpx_fdct4x4_sse2,      &vpx_idct4x4_16_add_c, 0,
+                   VPX_BITS_8)));
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_sse2, &vp9_iht4x4_16_add_c, 3, VPX_BITS_8)));
+#endif  // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    MSA, Trans4x4DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct4x4_msa, &vpx_idct4x4_16_add_msa, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    MSA, Trans4x4HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht4x4_msa, &vp9_iht4x4_16_add_msa, 3, VPX_BITS_8)));
+#endif  // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+}  // namespace
diff --git a/src/third_party/libvpx/test/fdct8x8_test.cc b/src/third_party/libvpx/test/fdct8x8_test.cc
new file mode 100644
index 0000000..29f2158
--- /dev/null
+++ b/src/third_party/libvpx/test/fdct8x8_test.cc
@@ -0,0 +1,791 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_codec.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+const int kNumCoeffs = 64;
+const double kPi = 3.141592653589793238462643383279502884;
+
+const int kSignBiasMaxDiff255 = 1500;
+const int kSignBiasMaxDiff15 = 10000;
+
+typedef void (*FdctFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*IdctFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef void (*FhtFunc)(const int16_t *in, tran_low_t *out, int stride,
+                        int tx_type);
+typedef void (*IhtFunc)(const tran_low_t *in, uint8_t *out, int stride,
+                        int tx_type);
+
+typedef std::tr1::tuple<FdctFunc, IdctFunc, int, vpx_bit_depth_t> Dct8x8Param;
+typedef std::tr1::tuple<FhtFunc, IhtFunc, int, vpx_bit_depth_t> Ht8x8Param;
+typedef std::tr1::tuple<IdctFunc, IdctFunc, int, vpx_bit_depth_t> Idct8x8Param;
+
+void reference_8x8_dct_1d(const double in[8], double out[8]) {
+  const double kInvSqrt2 = 0.707106781186547524400844362104;
+  for (int k = 0; k < 8; k++) {
+    out[k] = 0.0;
+    for (int n = 0; n < 8; n++)
+      out[k] += in[n] * cos(kPi * (2 * n + 1) * k / 16.0);
+    if (k == 0)
+      out[k] = out[k] * kInvSqrt2;
+  }
+}
+
+void reference_8x8_dct_2d(const int16_t input[kNumCoeffs],
+                          double output[kNumCoeffs]) {
+  // First transform columns
+  for (int i = 0; i < 8; ++i) {
+    double temp_in[8], temp_out[8];
+    for (int j = 0; j < 8; ++j)
+      temp_in[j] = input[j*8 + i];
+    reference_8x8_dct_1d(temp_in, temp_out);
+    for (int j = 0; j < 8; ++j)
+      output[j * 8 + i] = temp_out[j];
+  }
+  // Then transform rows
+  for (int i = 0; i < 8; ++i) {
+    double temp_in[8], temp_out[8];
+    for (int j = 0; j < 8; ++j)
+      temp_in[j] = output[j + i*8];
+    reference_8x8_dct_1d(temp_in, temp_out);
+    // Scale by some magic number
+    for (int j = 0; j < 8; ++j)
+      output[j + i * 8] = temp_out[j] * 2;
+  }
+}
+
+
+void fdct8x8_ref(const int16_t *in, tran_low_t *out, int stride,
+                 int /*tx_type*/) {
+  vpx_fdct8x8_c(in, out, stride);
+}
+
+void fht8x8_ref(const int16_t *in, tran_low_t *out, int stride, int tx_type) {
+  vp9_fht8x8_c(in, out, stride, tx_type);
+}
+
+#if CONFIG_VP9_HIGHBITDEPTH
+void idct8x8_10(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_64_add_c(in, out, stride, 10);
+}
+
+void idct8x8_12(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_64_add_c(in, out, stride, 12);
+}
+
+void iht8x8_10(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 10);
+}
+
+void iht8x8_12(const tran_low_t *in, uint8_t *out, int stride, int tx_type) {
+  vp9_highbd_iht8x8_64_add_c(in, out, stride, tx_type, 12);
+}
+
+#if HAVE_SSE2
+
+void idct8x8_10_add_10_c(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_10_add_c(in, out, stride, 10);
+}
+
+void idct8x8_10_add_12_c(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_10_add_c(in, out, stride, 12);
+}
+
+void idct8x8_10_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 10);
+}
+
+void idct8x8_10_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_10_add_sse2(in, out, stride, 12);
+}
+
+void idct8x8_64_add_10_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 10);
+}
+
+void idct8x8_64_add_12_sse2(const tran_low_t *in, uint8_t *out, int stride) {
+  vpx_highbd_idct8x8_64_add_sse2(in, out, stride, 12);
+}
+#endif  // HAVE_SSE2
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+class FwdTrans8x8TestBase {
+ public:
+  virtual ~FwdTrans8x8TestBase() {}
+
+ protected:
+  virtual void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) = 0;
+  virtual void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) = 0;
+
+  void RunSignBiasCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+    DECLARE_ALIGNED(16, tran_low_t, test_output_block[64]);
+    int count_sign_block[64][2];
+    const int count_test_block = 100000;
+
+    memset(count_sign_block, 0, sizeof(count_sign_block));
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-255, 255].
+      for (int j = 0; j < 64; ++j)
+        test_input_block[j] = ((rnd.Rand16() >> (16 - bit_depth_)) & mask_) -
+                              ((rnd.Rand16() >> (16 - bit_depth_)) & mask_);
+      ASM_REGISTER_STATE_CHECK(
+          RunFwdTxfm(test_input_block, test_output_block, pitch_));
+
+      for (int j = 0; j < 64; ++j) {
+        if (test_output_block[j] < 0)
+          ++count_sign_block[j][0];
+        else if (test_output_block[j] > 0)
+          ++count_sign_block[j][1];
+      }
+    }
+
+    for (int j = 0; j < 64; ++j) {
+      const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
+      const int max_diff = kSignBiasMaxDiff255;
+      EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
+          << "Error: 8x8 FDCT/FHT has a sign bias > "
+          << 1. * max_diff / count_test_block * 100 << "%"
+          << " for input range [-255, 255] at index " << j
+          << " count0: " << count_sign_block[j][0]
+          << " count1: " << count_sign_block[j][1]
+          << " diff: " << diff;
+    }
+
+    memset(count_sign_block, 0, sizeof(count_sign_block));
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_ / 16, mask_ / 16].
+      for (int j = 0; j < 64; ++j)
+        test_input_block[j] = ((rnd.Rand16() & mask_) >> 4) -
+                              ((rnd.Rand16() & mask_) >> 4);
+      ASM_REGISTER_STATE_CHECK(
+          RunFwdTxfm(test_input_block, test_output_block, pitch_));
+
+      for (int j = 0; j < 64; ++j) {
+        if (test_output_block[j] < 0)
+          ++count_sign_block[j][0];
+        else if (test_output_block[j] > 0)
+          ++count_sign_block[j][1];
+      }
+    }
+
+    for (int j = 0; j < 64; ++j) {
+      const int diff = abs(count_sign_block[j][0] - count_sign_block[j][1]);
+      const int max_diff = kSignBiasMaxDiff15;
+      EXPECT_LT(diff, max_diff << (bit_depth_ - 8))
+          << "Error: 8x8 FDCT/FHT has a sign bias > "
+          << 1. * max_diff / count_test_block * 100 << "%"
+          << " for input range [-15, 15] at index " << j
+          << " count0: " << count_sign_block[j][0]
+          << " count1: " << count_sign_block[j][1]
+          << " diff: " << diff;
+    }
+  }
+
+  void RunRoundTripErrorCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    int max_error = 0;
+    int total_error = 0;
+    const int count_test_block = 100000;
+    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+    DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
+    DECLARE_ALIGNED(16, uint8_t, dst[64]);
+    DECLARE_ALIGNED(16, uint8_t, src[64]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[64]);
+    DECLARE_ALIGNED(16, uint16_t, src16[64]);
+#endif
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < 64; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8();
+          dst[j] = rnd.Rand8();
+          test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand16() & mask_;
+          dst16[j] = rnd.Rand16() & mask_;
+          test_input_block[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      ASM_REGISTER_STATE_CHECK(
+          RunFwdTxfm(test_input_block, test_temp_block, pitch_));
+      for (int j = 0; j < 64; ++j) {
+          if (test_temp_block[j] > 0) {
+            test_temp_block[j] += 2;
+            test_temp_block[j] /= 4;
+            test_temp_block[j] *= 4;
+          } else {
+            test_temp_block[j] -= 2;
+            test_temp_block[j] /= 4;
+            test_temp_block[j] *= 4;
+          }
+      }
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
+#endif
+      }
+
+      for (int j = 0; j < 64; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const int diff = dst[j] - src[j];
+#endif
+        const int error = diff * diff;
+        if (max_error < error)
+          max_error = error;
+        total_error += error;
+      }
+    }
+
+    EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+      << "Error: 8x8 FDCT/IDCT or FHT/IHT has an individual"
+      << " roundtrip error > 1";
+
+    EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
+      << "Error: 8x8 FDCT/IDCT or FHT/IHT has average roundtrip "
+      << "error > 1/5 per block";
+  }
+
+  void RunExtremalCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    int max_error = 0;
+    int total_error = 0;
+    int total_coeff_error = 0;
+    const int count_test_block = 100000;
+    DECLARE_ALIGNED(16, int16_t, test_input_block[64]);
+    DECLARE_ALIGNED(16, tran_low_t, test_temp_block[64]);
+    DECLARE_ALIGNED(16, tran_low_t, ref_temp_block[64]);
+    DECLARE_ALIGNED(16, uint8_t, dst[64]);
+    DECLARE_ALIGNED(16, uint8_t, src[64]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[64]);
+    DECLARE_ALIGNED(16, uint16_t, src16[64]);
+#endif
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < 64; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          if (i == 0) {
+            src[j] = 255;
+            dst[j] = 0;
+          } else if (i == 1) {
+            src[j] = 0;
+            dst[j] = 255;
+          } else {
+            src[j] = rnd.Rand8() % 2 ? 255 : 0;
+            dst[j] = rnd.Rand8() % 2 ? 255 : 0;
+          }
+          test_input_block[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          if (i == 0) {
+            src16[j] = mask_;
+            dst16[j] = 0;
+          } else if (i == 1) {
+            src16[j] = 0;
+            dst16[j] = mask_;
+          } else {
+            src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+            dst16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+          }
+          test_input_block[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      ASM_REGISTER_STATE_CHECK(
+          RunFwdTxfm(test_input_block, test_temp_block, pitch_));
+      ASM_REGISTER_STATE_CHECK(
+          fwd_txfm_ref(test_input_block, ref_temp_block, pitch_, tx_type_));
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(
+            RunInvTxfm(test_temp_block, CONVERT_TO_BYTEPTR(dst16), pitch_));
+#endif
+      }
+
+      for (int j = 0; j < 64; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const int diff = dst[j] - src[j];
+#endif
+        const int error = diff * diff;
+        if (max_error < error)
+          max_error = error;
+        total_error += error;
+
+        const int coeff_diff = test_temp_block[j] - ref_temp_block[j];
+        total_coeff_error += abs(coeff_diff);
+      }
+
+      EXPECT_GE(1 << 2 * (bit_depth_ - 8), max_error)
+          << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has"
+          << "an individual roundtrip error > 1";
+
+      EXPECT_GE((count_test_block << 2 * (bit_depth_ - 8))/5, total_error)
+          << "Error: Extremal 8x8 FDCT/IDCT or FHT/IHT has average"
+          << " roundtrip error > 1/5 per block";
+
+      EXPECT_EQ(0, total_coeff_error)
+          << "Error: Extremal 8x8 FDCT/FHT has"
+          << "overflow issues in the intermediate steps > 1";
+    }
+  }
+
+  void RunInvAccuracyCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, src[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, src16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+#endif
+
+    for (int i = 0; i < count_test_block; ++i) {
+      double out_r[kNumCoeffs];
+
+      // Initialize a test block with input range [-255, 255].
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (bit_depth_ == VPX_BITS_8) {
+          src[j] = rnd.Rand8() % 2 ? 255 : 0;
+          dst[j] = src[j] > 0 ? 0 : 255;
+          in[j] = src[j] - dst[j];
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          src16[j] = rnd.Rand8() % 2 ? mask_ : 0;
+          dst16[j] = src16[j] > 0 ? 0 : mask_;
+          in[j] = src16[j] - dst16[j];
+#endif
+        }
+      }
+
+      reference_8x8_dct_2d(in, out_r);
+      for (int j = 0; j < kNumCoeffs; ++j)
+        coeff[j] = static_cast<tran_low_t>(round(out_r[j]));
+
+      if (bit_depth_ == VPX_BITS_8) {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
+                                            pitch_));
+#endif
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - src[j] : dst16[j] - src16[j];
+#else
+        const int diff = dst[j] - src[j];
+#endif
+        const uint32_t error = diff * diff;
+        EXPECT_GE(1u << 2 * (bit_depth_ - 8), error)
+            << "Error: 8x8 IDCT has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+
+  void RunFwdAccuracyCheck() {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 1000;
+    DECLARE_ALIGNED(16, int16_t, in[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, coeff_r[kNumCoeffs]);
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+
+    for (int i = 0; i < count_test_block; ++i) {
+      double out_r[kNumCoeffs];
+
+      // Initialize a test block with input range [-mask_, mask_].
+      for (int j = 0; j < kNumCoeffs; ++j)
+        in[j] = rnd.Rand8() % 2 == 0 ? mask_ : -mask_;
+
+      RunFwdTxfm(in, coeff, pitch_);
+      reference_8x8_dct_2d(in, out_r);
+      for (int j = 0; j < kNumCoeffs; ++j)
+        coeff_r[j] = static_cast<tran_low_t>(round(out_r[j]));
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        const int32_t diff = coeff[j] - coeff_r[j];
+        const uint32_t error = diff * diff;
+        EXPECT_GE(9u << 2 * (bit_depth_ - 8), error)
+            << "Error: 8x8 DCT has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+
+void CompareInvReference(IdctFunc ref_txfm, int thresh) {
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+    const int count_test_block = 10000;
+    const int eob = 12;
+    DECLARE_ALIGNED(16, tran_low_t, coeff[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, dst[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint8_t, ref[kNumCoeffs]);
+#if CONFIG_VP9_HIGHBITDEPTH
+    DECLARE_ALIGNED(16, uint16_t, dst16[kNumCoeffs]);
+    DECLARE_ALIGNED(16, uint16_t, ref16[kNumCoeffs]);
+#endif
+    const int16_t *scan = vp9_default_scan_orders[TX_8X8].scan;
+
+    for (int i = 0; i < count_test_block; ++i) {
+      for (int j = 0; j < kNumCoeffs; ++j) {
+        if (j < eob) {
+          // Random values less than the threshold, either positive or negative
+          coeff[scan[j]] = rnd(thresh) * (1-2*(i%2));
+        } else {
+          coeff[scan[j]] = 0;
+        }
+        if (bit_depth_ == VPX_BITS_8) {
+          dst[j] = 0;
+          ref[j] = 0;
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          dst16[j] = 0;
+          ref16[j] = 0;
+#endif
+        }
+      }
+      if (bit_depth_ == VPX_BITS_8) {
+        ref_txfm(coeff, ref, pitch_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, dst, pitch_));
+#if CONFIG_VP9_HIGHBITDEPTH
+      } else {
+        ref_txfm(coeff, CONVERT_TO_BYTEPTR(ref16), pitch_);
+        ASM_REGISTER_STATE_CHECK(RunInvTxfm(coeff, CONVERT_TO_BYTEPTR(dst16),
+                                            pitch_));
+#endif
+      }
+
+      for (int j = 0; j < kNumCoeffs; ++j) {
+#if CONFIG_VP9_HIGHBITDEPTH
+        const int diff =
+            bit_depth_ == VPX_BITS_8 ? dst[j] - ref[j] : dst16[j] - ref16[j];
+#else
+        const int diff = dst[j] - ref[j];
+#endif
+        const uint32_t error = diff * diff;
+        EXPECT_EQ(0u, error)
+            << "Error: 8x8 IDCT has error " << error
+            << " at index " << j;
+      }
+    }
+  }
+  int pitch_;
+  int tx_type_;
+  FhtFunc fwd_txfm_ref;
+  vpx_bit_depth_t bit_depth_;
+  int mask_;
+};
+
+class FwdTrans8x8DCT
+    : public FwdTrans8x8TestBase,
+      public ::testing::TestWithParam<Dct8x8Param> {
+ public:
+  virtual ~FwdTrans8x8DCT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    pitch_    = 8;
+    fwd_txfm_ref = fdct8x8_ref;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride);
+  }
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+
+  FdctFunc fwd_txfm_;
+  IdctFunc inv_txfm_;
+};
+
+TEST_P(FwdTrans8x8DCT, SignBiasCheck) {
+  RunSignBiasCheck();
+}
+
+TEST_P(FwdTrans8x8DCT, RoundTripErrorCheck) {
+  RunRoundTripErrorCheck();
+}
+
+TEST_P(FwdTrans8x8DCT, ExtremalCheck) {
+  RunExtremalCheck();
+}
+
+TEST_P(FwdTrans8x8DCT, FwdAccuracyCheck) {
+  RunFwdAccuracyCheck();
+}
+
+TEST_P(FwdTrans8x8DCT, InvAccuracyCheck) {
+  RunInvAccuracyCheck();
+}
+
+class FwdTrans8x8HT
+    : public FwdTrans8x8TestBase,
+      public ::testing::TestWithParam<Ht8x8Param> {
+ public:
+  virtual ~FwdTrans8x8HT() {}
+
+  virtual void SetUp() {
+    fwd_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    tx_type_  = GET_PARAM(2);
+    pitch_    = 8;
+    fwd_txfm_ref = fht8x8_ref;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunFwdTxfm(int16_t *in, tran_low_t *out, int stride) {
+    fwd_txfm_(in, out, stride, tx_type_);
+  }
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride, tx_type_);
+  }
+
+  FhtFunc fwd_txfm_;
+  IhtFunc inv_txfm_;
+};
+
+TEST_P(FwdTrans8x8HT, SignBiasCheck) {
+  RunSignBiasCheck();
+}
+
+TEST_P(FwdTrans8x8HT, RoundTripErrorCheck) {
+  RunRoundTripErrorCheck();
+}
+
+TEST_P(FwdTrans8x8HT, ExtremalCheck) {
+  RunExtremalCheck();
+}
+
+class InvTrans8x8DCT
+    : public FwdTrans8x8TestBase,
+      public ::testing::TestWithParam<Idct8x8Param> {
+ public:
+  virtual ~InvTrans8x8DCT() {}
+
+  virtual void SetUp() {
+    ref_txfm_ = GET_PARAM(0);
+    inv_txfm_ = GET_PARAM(1);
+    thresh_ = GET_PARAM(2);
+    pitch_ = 8;
+    bit_depth_ = GET_PARAM(3);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  void RunInvTxfm(tran_low_t *out, uint8_t *dst, int stride) {
+    inv_txfm_(out, dst, stride);
+  }
+  void RunFwdTxfm(int16_t * /*out*/, tran_low_t * /*dst*/, int /*stride*/) {}
+
+  IdctFunc ref_txfm_;
+  IdctFunc inv_txfm_;
+  int thresh_;
+};
+
+TEST_P(InvTrans8x8DCT, CompareReference) {
+  CompareInvReference(ref_txfm_, thresh_);
+}
+
+using std::tr1::make_tuple;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8),
+        make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_10, 0, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct8x8_c, &idct8x8_12, 0, VPX_BITS_12)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_c, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    C, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 0, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 1, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 2, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_10, 3, VPX_BITS_10),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 0, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 1, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 2, VPX_BITS_12),
+        make_tuple(&vp9_highbd_fht8x8_c, &iht8x8_12, 3, VPX_BITS_12),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    C, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_neon, &vpx_idct8x8_64_add_neon, 0,
+                   VPX_BITS_8)));
+#endif  // HAVE_NEON_ASM && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_c, &vp9_iht8x8_64_add_neon, 3, VPX_BITS_8)));
+#endif  // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_sse2, 0,
+                   VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    SSE2, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_sse2, 3, VPX_BITS_8)));
+#endif  // HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_sse2, &vpx_idct8x8_64_add_c, 0, VPX_BITS_8),
+        make_tuple(&vpx_highbd_fdct8x8_c,
+                   &idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct8x8_sse2,
+                   &idct8x8_64_add_10_sse2, 12, VPX_BITS_10),
+        make_tuple(&vpx_highbd_fdct8x8_c,
+                   &idct8x8_64_add_12_sse2, 12, VPX_BITS_12),
+        make_tuple(&vpx_highbd_fdct8x8_sse2,
+                   &idct8x8_64_add_12_sse2, 12, VPX_BITS_12)));
+
+INSTANTIATE_TEST_CASE_P(
+    SSE2, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_sse2, &vp9_iht8x8_64_add_c, 3, VPX_BITS_8)));
+
+// Optimizations take effect at a threshold of 6201, so we use a value close to
+// that to test both branches.
+INSTANTIATE_TEST_CASE_P(
+    SSE2, InvTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&idct8x8_10_add_10_c,
+                   &idct8x8_10_add_10_sse2, 6225, VPX_BITS_10),
+        make_tuple(&idct8x8_10,
+                   &idct8x8_64_add_10_sse2, 6225, VPX_BITS_10),
+        make_tuple(&idct8x8_10_add_12_c,
+                   &idct8x8_10_add_12_sse2, 6225, VPX_BITS_12),
+        make_tuple(&idct8x8_12,
+                   &idct8x8_64_add_12_sse2, 6225, VPX_BITS_12)));
+#endif  // HAVE_SSE2 && CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 && \
+    !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSSE3, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_ssse3, &vpx_idct8x8_64_add_ssse3, 0,
+                   VPX_BITS_8)));
+#endif
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    MSA, FwdTrans8x8DCT,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_msa, &vpx_idct8x8_64_add_msa, 0, VPX_BITS_8)));
+INSTANTIATE_TEST_CASE_P(
+    MSA, FwdTrans8x8HT,
+    ::testing::Values(
+        make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 0, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 1, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 2, VPX_BITS_8),
+        make_tuple(&vp9_fht8x8_msa, &vp9_iht8x8_64_add_msa, 3, VPX_BITS_8)));
+#endif  // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+}  // namespace
diff --git a/src/third_party/libvpx/test/frame_size_tests.cc b/src/third_party/libvpx/test/frame_size_tests.cc
new file mode 100644
index 0000000..d39c8f6
--- /dev/null
+++ b/src/third_party/libvpx/test/frame_size_tests.cc
@@ -0,0 +1,96 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/video_source.h"
+
+namespace {
+
+class VP9FrameSizeTestsLarge
+    : public ::libvpx_test::EncoderTest,
+      public ::testing::Test {
+ protected:
+  VP9FrameSizeTestsLarge() : EncoderTest(&::libvpx_test::kVP9),
+                             expected_res_(VPX_CODEC_OK) {}
+  virtual ~VP9FrameSizeTestsLarge() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(::libvpx_test::kRealTime);
+  }
+
+  virtual bool HandleDecodeResult(const vpx_codec_err_t res_dec,
+                                  const libvpx_test::VideoSource& /*video*/,
+                                  libvpx_test::Decoder *decoder) {
+    EXPECT_EQ(expected_res_, res_dec) << decoder->DecodeError();
+    return !::testing::Test::HasFailure();
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_CPUUSED, 7);
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+      encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+      encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+      encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+    }
+  }
+
+  int expected_res_;
+};
+
+TEST_F(VP9FrameSizeTestsLarge, TestInvalidSizes) {
+  ::libvpx_test::RandomVideoSource video;
+
+#if CONFIG_SIZE_LIMIT
+  video.SetSize(DECODE_WIDTH_LIMIT + 16, DECODE_HEIGHT_LIMIT + 16);
+  video.set_limit(2);
+  expected_res_ = VPX_CODEC_CORRUPT_FRAME;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#endif
+}
+
+TEST_F(VP9FrameSizeTestsLarge, ValidSizes) {
+  ::libvpx_test::RandomVideoSource video;
+
+#if CONFIG_SIZE_LIMIT
+  video.SetSize(DECODE_WIDTH_LIMIT, DECODE_HEIGHT_LIMIT);
+  video.set_limit(2);
+  expected_res_ = VPX_CODEC_OK;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#else
+  // This test produces a pretty large single frame allocation,  (roughly
+  // 25 megabits). The encoder allocates a good number of these frames
+  // one for each lag in frames (for 2 pass), and then one for each possible
+  // reference buffer (8) - we can end up with up to 30 buffers of roughly this
+  // size or almost 1 gig of memory.
+  // In total the allocations will exceed 2GiB which may cause a failure with
+  // mingw + wine, use a smaller size in that case.
+#if defined(_WIN32) && !defined(_WIN64) || defined(__OS2__)
+  video.SetSize(4096, 3072);
+#else
+  video.SetSize(4096, 4096);
+#endif
+  video.set_limit(2);
+  expected_res_ = VPX_CODEC_OK;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+#endif
+}
+
+TEST_F(VP9FrameSizeTestsLarge, OneByOneVideo) {
+  ::libvpx_test::RandomVideoSource video;
+
+  video.SetSize(1, 1);
+  video.set_limit(2);
+  expected_res_ = VPX_CODEC_OK;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+}  // namespace
diff --git a/src/third_party/libvpx/test/hadamard_test.cc b/src/third_party/libvpx/test/hadamard_test.cc
new file mode 100644
index 0000000..7a5bd5b
--- /dev/null
+++ b/src/third_party/libvpx/test/hadamard_test.cc
@@ -0,0 +1,220 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 <algorithm>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+
+#include "test/acm_random.h"
+#include "test/register_state_check.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+
+typedef void (*HadamardFunc)(const int16_t *a, int a_stride, int16_t *b);
+
+void hadamard_loop(const int16_t *a, int a_stride, int16_t *out) {
+  int16_t b[8];
+  for (int i = 0; i < 8; i += 2) {
+    b[i + 0] = a[i * a_stride] + a[(i + 1) * a_stride];
+    b[i + 1] = a[i * a_stride] - a[(i + 1) * a_stride];
+  }
+  int16_t c[8];
+  for (int i = 0; i < 8; i += 4) {
+    c[i + 0] = b[i + 0] + b[i + 2];
+    c[i + 1] = b[i + 1] + b[i + 3];
+    c[i + 2] = b[i + 0] - b[i + 2];
+    c[i + 3] = b[i + 1] - b[i + 3];
+  }
+  out[0] = c[0] + c[4];
+  out[7] = c[1] + c[5];
+  out[3] = c[2] + c[6];
+  out[4] = c[3] + c[7];
+  out[2] = c[0] - c[4];
+  out[6] = c[1] - c[5];
+  out[1] = c[2] - c[6];
+  out[5] = c[3] - c[7];
+}
+
+void reference_hadamard8x8(const int16_t *a, int a_stride, int16_t *b) {
+  int16_t buf[64];
+  for (int i = 0; i < 8; ++i) {
+    hadamard_loop(a + i, a_stride, buf + i * 8);
+  }
+
+  for (int i = 0; i < 8; ++i) {
+    hadamard_loop(buf + i, 8, b + i * 8);
+  }
+}
+
+void reference_hadamard16x16(const int16_t *a, int a_stride, int16_t *b) {
+  /* The source is a 16x16 block. The destination is rearranged to 8x32.
+   * Input is 9 bit. */
+  reference_hadamard8x8(a + 0 + 0 * a_stride, a_stride, b + 0);
+  reference_hadamard8x8(a + 8 + 0 * a_stride, a_stride, b + 64);
+  reference_hadamard8x8(a + 0 + 8 * a_stride, a_stride, b + 128);
+  reference_hadamard8x8(a + 8 + 8 * a_stride, a_stride, b + 192);
+
+  /* Overlay the 8x8 blocks and combine. */
+  for (int i = 0; i < 64; ++i) {
+    /* 8x8 steps the range up to 15 bits. */
+    const int16_t a0 = b[0];
+    const int16_t a1 = b[64];
+    const int16_t a2 = b[128];
+    const int16_t a3 = b[192];
+
+    /* Prevent the result from escaping int16_t. */
+    const int16_t b0 = (a0 + a1) >> 1;
+    const int16_t b1 = (a0 - a1) >> 1;
+    const int16_t b2 = (a2 + a3) >> 1;
+    const int16_t b3 = (a2 - a3) >> 1;
+
+    /* Store a 16 bit value. */
+    b[  0] = b0 + b2;
+    b[ 64] = b1 + b3;
+    b[128] = b0 - b2;
+    b[192] = b1 - b3;
+
+    ++b;
+  }
+}
+
+class HadamardTestBase : public ::testing::TestWithParam<HadamardFunc> {
+ public:
+  virtual void SetUp() {
+    h_func_ = GetParam();
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+ protected:
+  HadamardFunc h_func_;
+  ACMRandom rnd_;
+};
+
+class Hadamard8x8Test : public HadamardTestBase {};
+
+TEST_P(Hadamard8x8Test, CompareReferenceRandom) {
+  DECLARE_ALIGNED(16, int16_t, a[64]);
+  DECLARE_ALIGNED(16, int16_t, b[64]);
+  int16_t b_ref[64];
+  for (int i = 0; i < 64; ++i) {
+    a[i] = rnd_.Rand9Signed();
+  }
+  memset(b, 0, sizeof(b));
+  memset(b_ref, 0, sizeof(b_ref));
+
+  reference_hadamard8x8(a, 8, b_ref);
+  ASM_REGISTER_STATE_CHECK(h_func_(a, 8, b));
+
+  // The order of the output is not important. Sort before checking.
+  std::sort(b, b + 64);
+  std::sort(b_ref, b_ref + 64);
+  EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+}
+
+TEST_P(Hadamard8x8Test, VaryStride) {
+  DECLARE_ALIGNED(16, int16_t, a[64 * 8]);
+  DECLARE_ALIGNED(16, int16_t, b[64]);
+  int16_t b_ref[64];
+  for (int i = 0; i < 64 * 8; ++i) {
+    a[i] = rnd_.Rand9Signed();
+  }
+
+  for (int i = 8; i < 64; i += 8) {
+    memset(b, 0, sizeof(b));
+    memset(b_ref, 0, sizeof(b_ref));
+
+    reference_hadamard8x8(a, i, b_ref);
+    ASM_REGISTER_STATE_CHECK(h_func_(a, i, b));
+
+    // The order of the output is not important. Sort before checking.
+    std::sort(b, b + 64);
+    std::sort(b_ref, b_ref + 64);
+    EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(C, Hadamard8x8Test,
+                        ::testing::Values(&vpx_hadamard_8x8_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(SSE2, Hadamard8x8Test,
+                        ::testing::Values(&vpx_hadamard_8x8_sse2));
+#endif  // HAVE_SSE2
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64
+INSTANTIATE_TEST_CASE_P(SSSE3, Hadamard8x8Test,
+                        ::testing::Values(&vpx_hadamard_8x8_ssse3));
+#endif  // HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64
+
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(NEON, Hadamard8x8Test,
+                        ::testing::Values(&vpx_hadamard_8x8_neon));
+#endif  // HAVE_NEON
+
+class Hadamard16x16Test : public HadamardTestBase {};
+
+TEST_P(Hadamard16x16Test, CompareReferenceRandom) {
+  DECLARE_ALIGNED(16, int16_t, a[16 * 16]);
+  DECLARE_ALIGNED(16, int16_t, b[16 * 16]);
+  int16_t b_ref[16 * 16];
+  for (int i = 0; i < 16 * 16; ++i) {
+    a[i] = rnd_.Rand9Signed();
+  }
+  memset(b, 0, sizeof(b));
+  memset(b_ref, 0, sizeof(b_ref));
+
+  reference_hadamard16x16(a, 16, b_ref);
+  ASM_REGISTER_STATE_CHECK(h_func_(a, 16, b));
+
+  // The order of the output is not important. Sort before checking.
+  std::sort(b, b + 16 * 16);
+  std::sort(b_ref, b_ref + 16 * 16);
+  EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+}
+
+TEST_P(Hadamard16x16Test, VaryStride) {
+  DECLARE_ALIGNED(16, int16_t, a[16 * 16 * 8]);
+  DECLARE_ALIGNED(16, int16_t, b[16 * 16]);
+  int16_t b_ref[16 * 16];
+  for (int i = 0; i < 16 * 16 * 8; ++i) {
+    a[i] = rnd_.Rand9Signed();
+  }
+
+  for (int i = 8; i < 64; i += 8) {
+    memset(b, 0, sizeof(b));
+    memset(b_ref, 0, sizeof(b_ref));
+
+    reference_hadamard16x16(a, i, b_ref);
+    ASM_REGISTER_STATE_CHECK(h_func_(a, i, b));
+
+    // The order of the output is not important. Sort before checking.
+    std::sort(b, b + 16 * 16);
+    std::sort(b_ref, b_ref + 16 * 16);
+    EXPECT_EQ(0, memcmp(b, b_ref, sizeof(b)));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(C, Hadamard16x16Test,
+                        ::testing::Values(&vpx_hadamard_16x16_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(SSE2, Hadamard16x16Test,
+                        ::testing::Values(&vpx_hadamard_16x16_sse2));
+#endif  // HAVE_SSE2
+
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(NEON, Hadamard16x16Test,
+                        ::testing::Values(&vpx_hadamard_16x16_neon));
+#endif  // HAVE_NEON
+}  // namespace
diff --git a/src/third_party/libvpx/test/i420_video_source.h b/src/third_party/libvpx/test/i420_video_source.h
new file mode 100644
index 0000000..0a18480
--- /dev/null
+++ b/src/third_party/libvpx/test/i420_video_source.h
@@ -0,0 +1,36 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_I420_VIDEO_SOURCE_H_
+#define TEST_I420_VIDEO_SOURCE_H_
+#include <cstdio>
+#include <cstdlib>
+#include <string>
+
+#include "test/yuv_video_source.h"
+
+namespace libvpx_test {
+
+// This class extends VideoSource to allow parsing of raw yv12
+// so that we can do actual file encodes.
+class I420VideoSource : public YUVVideoSource {
+ public:
+  I420VideoSource(const std::string &file_name,
+                  unsigned int width, unsigned int height,
+                  int rate_numerator, int rate_denominator,
+                  unsigned int start, int limit)
+      : YUVVideoSource(file_name, VPX_IMG_FMT_I420,
+                       width, height,
+                       rate_numerator, rate_denominator,
+                       start, limit) {}
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_I420_VIDEO_SOURCE_H_
diff --git a/src/third_party/libvpx/test/idct8x8_test.cc b/src/third_party/libvpx/test/idct8x8_test.cc
new file mode 100644
index 0000000..7f9d751
--- /dev/null
+++ b/src/third_party/libvpx/test/idct8x8_test.cc
@@ -0,0 +1,101 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "vpx/vpx_integer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+#ifdef _MSC_VER
+static int round(double x) {
+  if (x < 0)
+    return static_cast<int>(ceil(x - 0.5));
+  else
+    return static_cast<int>(floor(x + 0.5));
+}
+#endif
+
+void reference_dct_1d(double input[8], double output[8]) {
+  const double kPi = 3.141592653589793238462643383279502884;
+  const double kInvSqrt2 = 0.707106781186547524400844362104;
+  for (int k = 0; k < 8; k++) {
+    output[k] = 0.0;
+    for (int n = 0; n < 8; n++)
+      output[k] += input[n]*cos(kPi*(2*n+1)*k/16.0);
+    if (k == 0)
+      output[k] = output[k]*kInvSqrt2;
+  }
+}
+
+void reference_dct_2d(int16_t input[64], double output[64]) {
+  // First transform columns
+  for (int i = 0; i < 8; ++i) {
+    double temp_in[8], temp_out[8];
+    for (int j = 0; j < 8; ++j)
+      temp_in[j] = input[j*8 + i];
+    reference_dct_1d(temp_in, temp_out);
+    for (int j = 0; j < 8; ++j)
+      output[j*8 + i] = temp_out[j];
+  }
+  // Then transform rows
+  for (int i = 0; i < 8; ++i) {
+    double temp_in[8], temp_out[8];
+    for (int j = 0; j < 8; ++j)
+      temp_in[j] = output[j + i*8];
+    reference_dct_1d(temp_in, temp_out);
+    for (int j = 0; j < 8; ++j)
+      output[j + i*8] = temp_out[j];
+  }
+  // Scale by some magic number
+  for (int i = 0; i < 64; ++i)
+    output[i] *= 2;
+}
+
+TEST(VP9Idct8x8Test, AccuracyCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = 10000;
+  for (int i = 0; i < count_test_block; ++i) {
+    int16_t input[64];
+    tran_low_t coeff[64];
+    double output_r[64];
+    uint8_t dst[64], src[64];
+
+    for (int j = 0; j < 64; ++j) {
+      src[j] = rnd.Rand8();
+      dst[j] = rnd.Rand8();
+    }
+    // Initialize a test block with input range [-255, 255].
+    for (int j = 0; j < 64; ++j)
+      input[j] = src[j] - dst[j];
+
+    reference_dct_2d(input, output_r);
+    for (int j = 0; j < 64; ++j)
+      coeff[j] = round(output_r[j]);
+    vpx_idct8x8_64_add_c(coeff, dst, 8);
+    for (int j = 0; j < 64; ++j) {
+      const int diff = dst[j] - src[j];
+      const int error = diff * diff;
+      EXPECT_GE(1, error)
+          << "Error: 8x8 FDCT/IDCT has error " << error
+          << " at index " << j;
+    }
+  }
+}
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/idct_test.cc b/src/third_party/libvpx/test/idct_test.cc
new file mode 100644
index 0000000..39db3e4
--- /dev/null
+++ b/src/third_party/libvpx/test/idct_test.cc
@@ -0,0 +1,121 @@
+/*
+ *  Copyright (c) 2010 The WebM 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 "./vpx_config.h"
+#include "./vp8_rtcd.h"
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "vpx/vpx_integer.h"
+
+typedef void (*IdctFunc)(int16_t *input, unsigned char *pred_ptr,
+                         int pred_stride, unsigned char *dst_ptr,
+                         int dst_stride);
+namespace {
+class IDCTTest : public ::testing::TestWithParam<IdctFunc> {
+ protected:
+  virtual void SetUp() {
+    int i;
+
+    UUT = GetParam();
+    memset(input, 0, sizeof(input));
+    /* Set up guard blocks */
+    for (i = 0; i < 256; i++) output[i] = ((i & 0xF) < 4 && (i < 64)) ? 0 : -1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+  IdctFunc UUT;
+  int16_t input[16];
+  unsigned char output[256];
+  unsigned char predict[256];
+};
+
+TEST_P(IDCTTest, TestGuardBlocks) {
+  int i;
+
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(0, output[i]) << i;
+    else
+      EXPECT_EQ(255, output[i]);
+}
+
+TEST_P(IDCTTest, TestAllZeros) {
+  int i;
+
+  ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(0, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAllOnes) {
+  int i;
+
+  input[0] = 4;
+  ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(1, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestAddOne) {
+  int i;
+
+  for (i = 0; i < 256; i++) predict[i] = i;
+  input[0] = 4;
+  ASM_REGISTER_STATE_CHECK(UUT(input, predict, 16, output, 16));
+
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) < 4 && i < 64)
+      EXPECT_EQ(i + 1, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(255, output[i]) << "i==" << i;
+}
+
+TEST_P(IDCTTest, TestWithData) {
+  int i;
+
+  for (i = 0; i < 16; i++) input[i] = i;
+
+  ASM_REGISTER_STATE_CHECK(UUT(input, output, 16, output, 16));
+
+  for (i = 0; i < 256; i++)
+    if ((i & 0xF) > 3 || i > 63)
+      EXPECT_EQ(255, output[i]) << "i==" << i;
+    else if (i == 0)
+      EXPECT_EQ(11, output[i]) << "i==" << i;
+    else if (i == 34)
+      EXPECT_EQ(1, output[i]) << "i==" << i;
+    else if (i == 2 || i == 17 || i == 32)
+      EXPECT_EQ(3, output[i]) << "i==" << i;
+    else
+      EXPECT_EQ(0, output[i]) << "i==" << i;
+}
+
+INSTANTIATE_TEST_CASE_P(C, IDCTTest, ::testing::Values(vp8_short_idct4x4llm_c));
+#if HAVE_MMX
+INSTANTIATE_TEST_CASE_P(MMX, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_mmx));
+#endif
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(MSA, IDCTTest,
+                        ::testing::Values(vp8_short_idct4x4llm_msa));
+#endif
+}
diff --git a/src/third_party/libvpx/test/invalid_file_test.cc b/src/third_party/libvpx/test/invalid_file_test.cc
new file mode 100644
index 0000000..f4241eb
--- /dev/null
+++ b/src/third_party/libvpx/test/invalid_file_test.cc
@@ -0,0 +1,182 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 <cstdio>
+#include <cstdlib>
+#include <string>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+struct DecodeParam {
+  int threads;
+  const char *filename;
+};
+
+std::ostream &operator<<(std::ostream &os, const DecodeParam &dp) {
+  return os << "threads: " << dp.threads << " file: " << dp.filename;
+}
+
+class InvalidFileTest
+    : public ::libvpx_test::DecoderTest,
+      public ::libvpx_test::CodecTestWithParam<DecodeParam> {
+ protected:
+  InvalidFileTest() : DecoderTest(GET_PARAM(0)), res_file_(NULL) {}
+
+  virtual ~InvalidFileTest() {
+    if (res_file_ != NULL)
+      fclose(res_file_);
+  }
+
+  void OpenResFile(const std::string &res_file_name_) {
+    res_file_ = libvpx_test::OpenTestDataFile(res_file_name_);
+    ASSERT_TRUE(res_file_ != NULL) << "Result file open failed. Filename: "
+        << res_file_name_;
+  }
+
+  virtual bool HandleDecodeResult(
+      const vpx_codec_err_t res_dec,
+      const libvpx_test::CompressedVideoSource &video,
+      libvpx_test::Decoder *decoder) {
+    EXPECT_TRUE(res_file_ != NULL);
+    int expected_res_dec;
+
+    // Read integer result.
+    const int res = fscanf(res_file_, "%d", &expected_res_dec);
+    EXPECT_NE(res, EOF) << "Read result data failed";
+
+    // Check results match.
+    const DecodeParam input = GET_PARAM(1);
+    if (input.threads > 1) {
+      // The serial decode check is too strict for tile-threaded decoding as
+      // there is no guarantee on the decode order nor which specific error
+      // will take precedence. Currently a tile-level error is not forwarded so
+      // the frame will simply be marked corrupt.
+      EXPECT_TRUE(res_dec == expected_res_dec ||
+                  res_dec == VPX_CODEC_CORRUPT_FRAME)
+          << "Results don't match: frame number = " << video.frame_number()
+          << ". (" << decoder->DecodeError() << "). Expected: "
+          << expected_res_dec << " or " << VPX_CODEC_CORRUPT_FRAME;
+    } else {
+      EXPECT_EQ(expected_res_dec, res_dec)
+          << "Results don't match: frame number = " << video.frame_number()
+          << ". (" << decoder->DecodeError() << ")";
+    }
+
+    return !HasFailure();
+  }
+
+  void RunTest() {
+    const DecodeParam input = GET_PARAM(1);
+    libvpx_test::CompressedVideoSource *video = NULL;
+    vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+    cfg.threads = input.threads;
+    const std::string filename = input.filename;
+
+    // Open compressed video file.
+    if (filename.substr(filename.length() - 3, 3) == "ivf") {
+      video = new libvpx_test::IVFVideoSource(filename);
+    } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+#if CONFIG_WEBM_IO
+      video = new libvpx_test::WebMVideoSource(filename);
+#else
+      fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+              filename.c_str());
+      return;
+#endif
+    }
+    video->Init();
+
+    // Construct result file name. The file holds a list of expected integer
+    // results, one for each decoded frame.  Any result that doesn't match
+    // the files list will cause a test failure.
+    const std::string res_filename = filename + ".res";
+    OpenResFile(res_filename);
+
+    // Decode frame, and check the md5 matching.
+    ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg));
+    delete video;
+  }
+
+ private:
+  FILE *res_file_;
+};
+
+TEST_P(InvalidFileTest, ReturnCode) {
+  RunTest();
+}
+
+const DecodeParam kVP9InvalidFileTests[] = {
+  {1, "invalid-vp90-02-v2.webm"},
+#if CONFIG_VP9_HIGHBITDEPTH
+  {1, "invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf"},
+#endif
+  {1, "invalid-vp90-03-v3.webm"},
+  {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf"},
+  {1, "invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf"},
+  {1, "invalid-vp91-2-mixedrefcsp-444to420.ivf"},
+  {1, "invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf"},
+  {1, "invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf"},
+};
+
+VP9_INSTANTIATE_TEST_CASE(InvalidFileTest,
+                          ::testing::ValuesIn(kVP9InvalidFileTests));
+
+// This class will include test vectors that are expected to fail
+// peek. However they are still expected to have no fatal failures.
+class InvalidFileInvalidPeekTest : public InvalidFileTest {
+ protected:
+  InvalidFileInvalidPeekTest() : InvalidFileTest() {}
+  virtual void HandlePeekResult(libvpx_test::Decoder *const /*decoder*/,
+                                libvpx_test::CompressedVideoSource* /*video*/,
+                                const vpx_codec_err_t /*res_peek*/) {}
+};
+
+TEST_P(InvalidFileInvalidPeekTest, ReturnCode) {
+  RunTest();
+}
+
+const DecodeParam kVP9InvalidFileInvalidPeekTests[] = {
+  {1, "invalid-vp90-01-v3.webm"},
+};
+
+VP9_INSTANTIATE_TEST_CASE(InvalidFileInvalidPeekTest,
+                          ::testing::ValuesIn(kVP9InvalidFileInvalidPeekTests));
+
+const DecodeParam kMultiThreadedVP9InvalidFileTests[] = {
+  {4, "invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm"},
+  {4, "invalid-"
+      "vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf"},
+  {4, "invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf"},
+  {2, "invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf"},
+  {4, "invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf"},
+};
+
+INSTANTIATE_TEST_CASE_P(
+    VP9MultiThreaded, InvalidFileTest,
+    ::testing::Combine(
+        ::testing::Values(
+            static_cast<const libvpx_test::CodecFactory*>(&libvpx_test::kVP9)),
+        ::testing::ValuesIn(kMultiThreadedVP9InvalidFileTests)));
+}  // namespace
diff --git a/src/third_party/libvpx/test/ivf_video_source.h b/src/third_party/libvpx/test/ivf_video_source.h
new file mode 100644
index 0000000..824a39d
--- /dev/null
+++ b/src/third_party/libvpx/test/ivf_video_source.h
@@ -0,0 +1,111 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_IVF_VIDEO_SOURCE_H_
+#define TEST_IVF_VIDEO_SOURCE_H_
+#include <cstdio>
+#include <cstdlib>
+#include <new>
+#include <string>
+#include "test/video_source.h"
+
+namespace libvpx_test {
+const unsigned int kCodeBufferSize = 256 * 1024;
+const unsigned int kIvfFileHdrSize = 32;
+const unsigned int kIvfFrameHdrSize = 12;
+
+static unsigned int MemGetLe32(const uint8_t *mem) {
+  return (mem[3] << 24) | (mem[2] << 16) | (mem[1] << 8) | (mem[0]);
+}
+
+// This class extends VideoSource to allow parsing of ivf files,
+// so that we can do actual file decodes.
+class IVFVideoSource : public CompressedVideoSource {
+ public:
+  explicit IVFVideoSource(const std::string &file_name)
+      : file_name_(file_name),
+        input_file_(NULL),
+        compressed_frame_buf_(NULL),
+        frame_sz_(0),
+        frame_(0),
+        end_of_file_(false) {
+  }
+
+  virtual ~IVFVideoSource() {
+    delete[] compressed_frame_buf_;
+
+    if (input_file_)
+      fclose(input_file_);
+  }
+
+  virtual void Init() {
+    // Allocate a buffer for read in the compressed video frame.
+    compressed_frame_buf_ = new uint8_t[libvpx_test::kCodeBufferSize];
+    ASSERT_TRUE(compressed_frame_buf_ != NULL)
+        << "Allocate frame buffer failed";
+  }
+
+  virtual void Begin() {
+    input_file_ = OpenTestDataFile(file_name_);
+    ASSERT_TRUE(input_file_ != NULL) << "Input file open failed. Filename: "
+        << file_name_;
+
+    // Read file header
+    uint8_t file_hdr[kIvfFileHdrSize];
+    ASSERT_EQ(kIvfFileHdrSize, fread(file_hdr, 1, kIvfFileHdrSize, input_file_))
+        << "File header read failed.";
+    // Check file header
+    ASSERT_TRUE(file_hdr[0] == 'D' && file_hdr[1] == 'K' && file_hdr[2] == 'I'
+                && file_hdr[3] == 'F') << "Input is not an IVF file.";
+
+    FillFrame();
+  }
+
+  virtual void Next() {
+    ++frame_;
+    FillFrame();
+  }
+
+  void FillFrame() {
+    ASSERT_TRUE(input_file_ != NULL);
+    uint8_t frame_hdr[kIvfFrameHdrSize];
+    // Check frame header and read a frame from input_file.
+    if (fread(frame_hdr, 1, kIvfFrameHdrSize, input_file_)
+        != kIvfFrameHdrSize) {
+      end_of_file_ = true;
+    } else {
+      end_of_file_ = false;
+
+      frame_sz_ = MemGetLe32(frame_hdr);
+      ASSERT_LE(frame_sz_, kCodeBufferSize)
+          << "Frame is too big for allocated code buffer";
+      ASSERT_EQ(frame_sz_,
+                fread(compressed_frame_buf_, 1, frame_sz_, input_file_))
+          << "Failed to read complete frame";
+    }
+  }
+
+  virtual const uint8_t *cxdata() const {
+    return end_of_file_ ? NULL : compressed_frame_buf_;
+  }
+  virtual size_t frame_size() const { return frame_sz_; }
+  virtual unsigned int frame_number() const { return frame_; }
+
+ protected:
+  std::string file_name_;
+  FILE *input_file_;
+  uint8_t *compressed_frame_buf_;
+  size_t frame_sz_;
+  unsigned int frame_;
+  bool end_of_file_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_IVF_VIDEO_SOURCE_H_
diff --git a/src/third_party/libvpx/test/keyframe_test.cc b/src/third_party/libvpx/test/keyframe_test.cc
new file mode 100644
index 0000000..d8b21a1
--- /dev/null
+++ b/src/third_party/libvpx/test/keyframe_test.cc
@@ -0,0 +1,145 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+class KeyframeTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  KeyframeTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~KeyframeTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    kf_count_ = 0;
+    kf_count_max_ = INT_MAX;
+    kf_do_force_kf_ = false;
+    set_cpu_used_ = 0;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (kf_do_force_kf_)
+      frame_flags_ = (video->frame() % 3) ? 0 : VPX_EFLAG_FORCE_KF;
+    if (set_cpu_used_ && video->frame() == 1)
+      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+  }
+
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+      kf_pts_list_.push_back(pkt->data.frame.pts);
+      kf_count_++;
+      abort_ |= kf_count_ > kf_count_max_;
+    }
+  }
+
+  bool kf_do_force_kf_;
+  int kf_count_;
+  int kf_count_max_;
+  std::vector<vpx_codec_pts_t> kf_pts_list_;
+  int set_cpu_used_;
+};
+
+TEST_P(KeyframeTest, TestRandomVideoSource) {
+  // Validate that encoding the RandomVideoSource produces multiple keyframes.
+  // This validates the results of the TestDisableKeyframes test.
+  kf_count_max_ = 2;  // early exit successful tests.
+
+  ::libvpx_test::RandomVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // In realtime mode - auto placed keyframes are exceedingly rare,  don't
+  // bother with this check   if(GetParam() > 0)
+  if (GET_PARAM(1) > 0)
+    EXPECT_GT(kf_count_, 1);
+}
+
+TEST_P(KeyframeTest, TestDisableKeyframes) {
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  kf_count_max_ = 1;  // early exit failed tests.
+
+  ::libvpx_test::RandomVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  EXPECT_EQ(1, kf_count_);
+}
+
+TEST_P(KeyframeTest, TestForceKeyframe) {
+  cfg_.kf_mode = VPX_KF_DISABLED;
+  kf_do_force_kf_ = true;
+
+  ::libvpx_test::DummyVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // verify that every third frame is a keyframe.
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
+    ASSERT_EQ(0, *iter % 3) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
+TEST_P(KeyframeTest, TestKeyframeMaxDistance) {
+  cfg_.kf_max_dist = 25;
+
+  ::libvpx_test::DummyVideoSource video;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // verify that keyframe interval matches kf_max_dist
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
+    ASSERT_EQ(0, *iter % 25) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
+TEST_P(KeyframeTest, TestAutoKeyframe) {
+  cfg_.kf_mode = VPX_KF_AUTO;
+  kf_do_force_kf_ = false;
+
+  // Force a deterministic speed step in Real Time mode, as the faster modes
+  // may not produce a keyframe like we expect. This is necessary when running
+  // on very slow environments (like Valgrind). The step -11 was determined
+  // experimentally as the fastest mode that still throws the keyframe.
+  if (deadline_ == VPX_DL_REALTIME)
+    set_cpu_used_ = -11;
+
+  // This clip has a cut scene every 30 frames -> Frame 0, 30, 60, 90, 120.
+  // I check only the first 40 frames to make sure there's a keyframe at frame
+  // 0 and 30.
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 40);
+
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  // In realtime mode - auto placed keyframes are exceedingly rare,  don't
+  // bother with this check
+  if (GET_PARAM(1) > 0)
+    EXPECT_EQ(2u, kf_pts_list_.size()) << " Not the right number of keyframes ";
+
+  // Verify that keyframes match the file keyframes in the file.
+  for (std::vector<vpx_codec_pts_t>::const_iterator iter = kf_pts_list_.begin();
+       iter != kf_pts_list_.end(); ++iter) {
+    if (deadline_ == VPX_DL_REALTIME && *iter > 0)
+      EXPECT_EQ(0, (*iter - 1) % 30) << "Unexpected keyframe at frame "
+        << *iter;
+    else
+      EXPECT_EQ(0, *iter % 30) << "Unexpected keyframe at frame " << *iter;
+  }
+}
+
+VP8_INSTANTIATE_TEST_CASE(KeyframeTest, ALL_TEST_MODES);
+}  // namespace
diff --git a/src/third_party/libvpx/test/level_test.cc b/src/third_party/libvpx/test/level_test.cc
new file mode 100644
index 0000000..62d0247
--- /dev/null
+++ b/src/third_party/libvpx/test/level_test.cc
@@ -0,0 +1,119 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+class LevelTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  LevelTest()
+     : EncoderTest(GET_PARAM(0)),
+       encoding_mode_(GET_PARAM(1)),
+       cpu_used_(GET_PARAM(2)),
+       min_gf_internal_(24),
+       target_level_(0),
+       level_(0) {}
+  virtual ~LevelTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(encoding_mode_);
+    if (encoding_mode_ != ::libvpx_test::kRealTime) {
+      cfg_.g_lag_in_frames = 25;
+      cfg_.rc_end_usage = VPX_VBR;
+    } else {
+      cfg_.g_lag_in_frames = 0;
+      cfg_.rc_end_usage = VPX_CBR;
+    }
+    cfg_.rc_2pass_vbr_minsection_pct = 5;
+    cfg_.rc_2pass_vbr_maxsection_pct = 2000;
+    cfg_.rc_target_bitrate = 400;
+    cfg_.rc_max_quantizer = 63;
+    cfg_.rc_min_quantizer = 0;
+  }
+
+  virtual void PreEncodeFrameHook(::libvpx_test::VideoSource *video,
+                                  ::libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      encoder->Control(VP8E_SET_CPUUSED, cpu_used_);
+      encoder->Control(VP9E_SET_TARGET_LEVEL, target_level_);
+      encoder->Control(VP9E_SET_MIN_GF_INTERVAL, min_gf_internal_);
+      if (encoding_mode_ != ::libvpx_test::kRealTime) {
+        encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+        encoder->Control(VP8E_SET_ARNR_MAXFRAMES, 7);
+        encoder->Control(VP8E_SET_ARNR_STRENGTH, 5);
+        encoder->Control(VP8E_SET_ARNR_TYPE, 3);
+      }
+    }
+    encoder->Control(VP9E_GET_LEVEL, &level_);
+    ASSERT_LE(level_, 51);
+    ASSERT_GE(level_, 0);
+  }
+
+  ::libvpx_test::TestMode encoding_mode_;
+  int cpu_used_;
+  int min_gf_internal_;
+  int target_level_;
+  int level_;
+};
+
+// Test for keeping level stats only
+TEST_P(LevelTest, TestTargetLevel0) {
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       40);
+  target_level_ = 0;
+  min_gf_internal_ = 4;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_EQ(11, level_);
+
+  cfg_.rc_target_bitrate = 1600;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  ASSERT_EQ(20, level_);
+}
+
+// Test for level control being turned off
+TEST_P(LevelTest, TestTargetLevel255) {
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0,
+                                       30);
+  target_level_ = 255;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+TEST_P(LevelTest, TestTargetLevelApi) {
+  ::libvpx_test::I420VideoSource video("hantro_odd.yuv", 208, 144, 30, 1, 0, 1);
+  static const vpx_codec_iface_t *codec = &vpx_codec_vp9_cx_algo;
+  vpx_codec_ctx_t enc;
+  vpx_codec_enc_cfg_t cfg;
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_config_default(codec, &cfg, 0));
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_enc_init(&enc, codec, &cfg, 0));
+  for (int level = 0; level <= 256; ++level) {
+    if (level == 10 || level == 11 || level == 20 || level == 21 ||
+        level == 30 || level == 31 || level == 40 || level == 41 ||
+        level == 50 || level == 51 || level == 52 || level == 60 ||
+        level == 61 || level == 62 || level == 0 || level == 255)
+      EXPECT_EQ(VPX_CODEC_OK,
+                vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
+    else
+      EXPECT_EQ(VPX_CODEC_INVALID_PARAM,
+                vpx_codec_control(&enc, VP9E_SET_TARGET_LEVEL, level));
+  }
+  EXPECT_EQ(VPX_CODEC_OK, vpx_codec_destroy(&enc));
+}
+
+VP9_INSTANTIATE_TEST_CASE(LevelTest,
+                          ::testing::Values(::libvpx_test::kTwoPassGood,
+                                            ::libvpx_test::kOnePassGood),
+                          ::testing::Range(0, 9));
+}  // namespace
diff --git a/src/third_party/libvpx/test/lpf_8_test.cc b/src/third_party/libvpx/test/lpf_8_test.cc
new file mode 100644
index 0000000..94646e4
--- /dev/null
+++ b/src/third_party/libvpx/test/lpf_8_test.cc
@@ -0,0 +1,672 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 <cmath>
+#include <cstdlib>
+#include <string>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_entropy.h"
+#include "vp9/common/vp9_loopfilter.h"
+#include "vpx/vpx_integer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+// Horizontally and Vertically need 32x32: 8  Coeffs preceeding filtered section
+//                                         16 Coefs within filtered section
+//                                         8  Coeffs following filtered section
+const int kNumCoeffs = 1024;
+
+const int number_of_iterations = 10000;
+
+#if CONFIG_VP9_HIGHBITDEPTH
+typedef void (*loop_op_t)(uint16_t *s, int p, const uint8_t *blimit,
+                          const uint8_t *limit, const uint8_t *thresh,
+                          int bd);
+typedef void (*dual_loop_op_t)(uint16_t *s, int p, const uint8_t *blimit0,
+                               const uint8_t *limit0, const uint8_t *thresh0,
+                               const uint8_t *blimit1, const uint8_t *limit1,
+                               const uint8_t *thresh1, int bd);
+#else
+typedef void (*loop_op_t)(uint8_t *s, int p, const uint8_t *blimit,
+                          const uint8_t *limit, const uint8_t *thresh);
+typedef void (*dual_loop_op_t)(uint8_t *s, int p, const uint8_t *blimit0,
+                               const uint8_t *limit0, const uint8_t *thresh0,
+                               const uint8_t *blimit1, const uint8_t *limit1,
+                               const uint8_t *thresh1);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+typedef std::tr1::tuple<loop_op_t, loop_op_t, int> loop8_param_t;
+typedef std::tr1::tuple<dual_loop_op_t, dual_loop_op_t, int> dualloop8_param_t;
+
+class Loop8Test6Param : public ::testing::TestWithParam<loop8_param_t> {
+ public:
+  virtual ~Loop8Test6Param() {}
+  virtual void SetUp() {
+    loopfilter_op_ = GET_PARAM(0);
+    ref_loopfilter_op_ = GET_PARAM(1);
+    bit_depth_ = GET_PARAM(2);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  int bit_depth_;
+  int mask_;
+  loop_op_t loopfilter_op_;
+  loop_op_t ref_loopfilter_op_;
+};
+
+class Loop8Test9Param : public ::testing::TestWithParam<dualloop8_param_t> {
+ public:
+  virtual ~Loop8Test9Param() {}
+  virtual void SetUp() {
+    loopfilter_op_ = GET_PARAM(0);
+    ref_loopfilter_op_ = GET_PARAM(1);
+    bit_depth_ = GET_PARAM(2);
+    mask_ = (1 << bit_depth_) - 1;
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  int bit_depth_;
+  int mask_;
+  dual_loop_op_t loopfilter_op_;
+  dual_loop_op_t ref_loopfilter_op_;
+};
+
+TEST_P(Loop8Test6Param, OperationCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = number_of_iterations;
+#if CONFIG_VP9_HIGHBITDEPTH
+  int32_t bd = bit_depth_;
+  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
+#else
+  DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  int err_count_total = 0;
+  int first_failure = -1;
+  for (int i = 0; i < count_test_block; ++i) {
+    int err_count = 0;
+    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    int32_t p = kNumCoeffs/32;
+
+    uint16_t tmp_s[kNumCoeffs];
+    int j = 0;
+    while (j < kNumCoeffs) {
+      uint8_t val = rnd.Rand8();
+      if (val & 0x80) {  // 50% chance to choose a new value.
+        tmp_s[j] = rnd.Rand16();
+        j++;
+      } else {  // 50% chance to repeat previous value in row X times
+        int k = 0;
+        while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
+          if (j < 1) {
+            tmp_s[j] = rnd.Rand16();
+          } else if (val & 0x20) {  // Increment by an value within the limit
+            tmp_s[j] = (tmp_s[j - 1] + (*limit - 1));
+          } else {  // Decrement by an value within the limit
+            tmp_s[j] = (tmp_s[j - 1] - (*limit - 1));
+          }
+          j++;
+        }
+      }
+    }
+    for (j = 0; j < kNumCoeffs; j++) {
+      if (i % 2) {
+        s[j] = tmp_s[j] & mask_;
+      } else {
+        s[j] = tmp_s[p * (j % p) + j / p] & mask_;
+      }
+      ref_s[j] = s[j];
+    }
+#if CONFIG_VP9_HIGHBITDEPTH
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd));
+#else
+    ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      err_count += ref_s[j] != s[j];
+    }
+    if (err_count && !err_count_total) {
+      first_failure = i;
+    }
+    err_count_total += err_count;
+  }
+  EXPECT_EQ(0, err_count_total)
+      << "Error: Loop8Test6Param, C output doesn't match SSE2 "
+         "loopfilter output. "
+      << "First failed at test case " << first_failure;
+}
+
+TEST_P(Loop8Test6Param, ValueCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = number_of_iterations;
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int32_t bd = bit_depth_;
+  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
+#else
+  DECLARE_ALIGNED(8, uint8_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(8, uint8_t, ref_s[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  int err_count_total = 0;
+  int first_failure = -1;
+
+  // NOTE: The code in vp9_loopfilter.c:update_sharpness computes mblim as a
+  // function of sharpness_lvl and the loopfilter lvl as:
+  // block_inside_limit = lvl >> ((sharpness_lvl > 0) + (sharpness_lvl > 4));
+  // ...
+  // memset(lfi->lfthr[lvl].mblim, (2 * (lvl + 2) + block_inside_limit),
+  //        SIMD_WIDTH);
+  // This means that the largest value for mblim will occur when sharpness_lvl
+  // is equal to 0, and lvl is equal to its greatest value (MAX_LOOP_FILTER).
+  // In this case block_inside_limit will be equal to MAX_LOOP_FILTER and
+  // therefore mblim will be equal to (2 * (lvl + 2) + block_inside_limit) =
+  // 2 * (MAX_LOOP_FILTER + 2) + MAX_LOOP_FILTER = 3 * MAX_LOOP_FILTER + 4
+
+  for (int i = 0; i < count_test_block; ++i) {
+    int err_count = 0;
+    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    int32_t p = kNumCoeffs / 32;
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      s[j] = rnd.Rand16() & mask_;
+      ref_s[j] = s[j];
+    }
+#if CONFIG_VP9_HIGHBITDEPTH
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit, limit, thresh, bd);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh, bd));
+#else
+    ref_loopfilter_op_(ref_s+8+p*8, p, blimit, limit, thresh);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit, limit, thresh));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      err_count += ref_s[j] != s[j];
+    }
+    if (err_count && !err_count_total) {
+      first_failure = i;
+    }
+    err_count_total += err_count;
+  }
+  EXPECT_EQ(0, err_count_total)
+      << "Error: Loop8Test6Param, C output doesn't match SSE2 "
+         "loopfilter output. "
+      << "First failed at test case " << first_failure;
+}
+
+TEST_P(Loop8Test9Param, OperationCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = number_of_iterations;
+#if CONFIG_VP9_HIGHBITDEPTH
+  const int32_t bd = bit_depth_;
+  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
+#else
+  DECLARE_ALIGNED(8,  uint8_t,  s[kNumCoeffs]);
+  DECLARE_ALIGNED(8,  uint8_t,  ref_s[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  int err_count_total = 0;
+  int first_failure = -1;
+  for (int i = 0; i < count_test_block; ++i) {
+    int err_count = 0;
+    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit0[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit1[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    int32_t p = kNumCoeffs / 32;
+    uint16_t tmp_s[kNumCoeffs];
+    int j = 0;
+    const uint8_t limit = *limit0 < *limit1 ? *limit0 : *limit1;
+    while (j < kNumCoeffs) {
+      uint8_t val = rnd.Rand8();
+      if (val & 0x80) {  // 50% chance to choose a new value.
+        tmp_s[j] = rnd.Rand16();
+        j++;
+      } else {  // 50% chance to repeat previous value in row X times.
+        int k = 0;
+        while (k++ < ((val & 0x1f) + 1) && j < kNumCoeffs) {
+          if (j < 1) {
+            tmp_s[j] = rnd.Rand16();
+          } else if (val & 0x20) {  // Increment by a value within the limit.
+            tmp_s[j] = (tmp_s[j - 1] + (limit - 1));
+          } else {  // Decrement by an value within the limit.
+            tmp_s[j] = (tmp_s[j - 1] - (limit - 1));
+          }
+          j++;
+        }
+      }
+    }
+    for (j = 0; j < kNumCoeffs; j++) {
+      if (i % 2) {
+        s[j] = tmp_s[j] & mask_;
+      } else {
+        s[j] = tmp_s[p * (j % p) + j / p] & mask_;
+      }
+      ref_s[j] = s[j];
+    }
+#if CONFIG_VP9_HIGHBITDEPTH
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1, bd);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1, bd));
+#else
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      err_count += ref_s[j] != s[j];
+    }
+    if (err_count && !err_count_total) {
+      first_failure = i;
+    }
+    err_count_total += err_count;
+  }
+  EXPECT_EQ(0, err_count_total)
+      << "Error: Loop8Test9Param, C output doesn't match SSE2 "
+         "loopfilter output. "
+      << "First failed at test case " << first_failure;
+}
+
+TEST_P(Loop8Test9Param, ValueCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  const int count_test_block = number_of_iterations;
+#if CONFIG_VP9_HIGHBITDEPTH
+  DECLARE_ALIGNED(16, uint16_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(16, uint16_t, ref_s[kNumCoeffs]);
+#else
+  DECLARE_ALIGNED(8,  uint8_t, s[kNumCoeffs]);
+  DECLARE_ALIGNED(8,  uint8_t, ref_s[kNumCoeffs]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+  int err_count_total = 0;
+  int first_failure = -1;
+  for (int i = 0; i < count_test_block; ++i) {
+    int err_count = 0;
+    uint8_t tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit0[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit0[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh0[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(3 * MAX_LOOP_FILTER + 4));
+    DECLARE_ALIGNED(16, const uint8_t, blimit1[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = static_cast<uint8_t>(rnd(MAX_LOOP_FILTER));
+    DECLARE_ALIGNED(16, const uint8_t, limit1[16])  = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    tmp = rnd.Rand8();
+    DECLARE_ALIGNED(16, const uint8_t, thresh1[16]) = {
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp,
+        tmp, tmp, tmp, tmp, tmp, tmp, tmp, tmp
+    };
+    int32_t p = kNumCoeffs / 32;  // TODO(pdlf) can we have non-square here?
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      s[j] = rnd.Rand16() & mask_;
+      ref_s[j] = s[j];
+    }
+#if CONFIG_VP9_HIGHBITDEPTH
+    const int32_t bd = bit_depth_;
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1, bd);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0,
+                       thresh0, blimit1, limit1, thresh1, bd));
+#else
+    ref_loopfilter_op_(ref_s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1);
+    ASM_REGISTER_STATE_CHECK(
+        loopfilter_op_(s + 8 + p * 8, p, blimit0, limit0, thresh0,
+                       blimit1, limit1, thresh1));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int j = 0; j < kNumCoeffs; ++j) {
+      err_count += ref_s[j] != s[j];
+    }
+    if (err_count && !err_count_total) {
+      first_failure = i;
+    }
+    err_count_total += err_count;
+  }
+  EXPECT_EQ(0, err_count_total)
+      << "Error: Loop8Test9Param, C output doesn't match SSE2"
+         "loopfilter output. "
+      << "First failed at test case " << first_failure;
+}
+
+using std::tr1::make_tuple;
+
+#if HAVE_SSE2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Loop8Test6Param,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+                   &vpx_highbd_lpf_horizontal_4_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+                   &vpx_highbd_lpf_vertical_4_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+                   &vpx_highbd_lpf_horizontal_8_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_8_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_16_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+                   &vpx_highbd_lpf_vertical_8_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+                   &vpx_highbd_lpf_vertical_16_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+                   &vpx_highbd_lpf_horizontal_4_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+                   &vpx_highbd_lpf_vertical_4_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+                   &vpx_highbd_lpf_horizontal_8_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_8_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_16_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+                   &vpx_highbd_lpf_vertical_8_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+                   &vpx_highbd_lpf_vertical_16_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_4_sse2,
+                   &vpx_highbd_lpf_horizontal_4_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_4_sse2,
+                   &vpx_highbd_lpf_vertical_4_c, 12),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_sse2,
+                   &vpx_highbd_lpf_horizontal_8_c, 12),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_8_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_8_c, 12),
+        make_tuple(&vpx_highbd_lpf_horizontal_edge_16_sse2,
+                   &vpx_highbd_lpf_horizontal_edge_16_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_8_sse2,
+                   &vpx_highbd_lpf_vertical_8_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_16_sse2,
+                   &vpx_highbd_lpf_vertical_16_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+                   &vpx_highbd_lpf_vertical_16_dual_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+                   &vpx_highbd_lpf_vertical_16_dual_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_16_dual_sse2,
+                   &vpx_highbd_lpf_vertical_16_dual_c, 12)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Loop8Test6Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_sse2,
+                   &vpx_lpf_horizontal_4_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_sse2,
+                   &vpx_lpf_horizontal_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_8_sse2,
+                   &vpx_lpf_horizontal_edge_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_16_sse2,
+                   &vpx_lpf_horizontal_edge_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_sse2,
+                   &vpx_lpf_vertical_4_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_sse2,
+                   &vpx_lpf_vertical_8_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_sse2,
+                   &vpx_lpf_vertical_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_dual_sse2,
+                   &vpx_lpf_vertical_16_dual_c, 8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+#endif
+
+#if HAVE_AVX2 && (!CONFIG_VP9_HIGHBITDEPTH)
+INSTANTIATE_TEST_CASE_P(
+    AVX2, Loop8Test6Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_edge_8_avx2,
+                   &vpx_lpf_horizontal_edge_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_16_avx2,
+                   &vpx_lpf_horizontal_edge_16_c, 8)));
+#endif
+
+#if HAVE_SSE2
+#if CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Loop8Test9Param,
+    ::testing::Values(
+        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_4_dual_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_8_dual_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+                   &vpx_highbd_lpf_vertical_4_dual_c, 8),
+        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+                   &vpx_highbd_lpf_vertical_8_dual_c, 8),
+        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_4_dual_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_8_dual_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+                   &vpx_highbd_lpf_vertical_4_dual_c, 10),
+        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+                   &vpx_highbd_lpf_vertical_8_dual_c, 10),
+        make_tuple(&vpx_highbd_lpf_horizontal_4_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_4_dual_c, 12),
+        make_tuple(&vpx_highbd_lpf_horizontal_8_dual_sse2,
+                   &vpx_highbd_lpf_horizontal_8_dual_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_4_dual_sse2,
+                   &vpx_highbd_lpf_vertical_4_dual_c, 12),
+        make_tuple(&vpx_highbd_lpf_vertical_8_dual_sse2,
+                   &vpx_highbd_lpf_vertical_8_dual_c, 12)));
+#else
+INSTANTIATE_TEST_CASE_P(
+    SSE2, Loop8Test9Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_dual_sse2,
+                   &vpx_lpf_horizontal_4_dual_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_dual_sse2,
+                   &vpx_lpf_horizontal_8_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_dual_sse2,
+                   &vpx_lpf_vertical_4_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_dual_sse2,
+                   &vpx_lpf_vertical_8_dual_c, 8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+#endif
+
+#if HAVE_NEON
+#if CONFIG_VP9_HIGHBITDEPTH
+// No neon high bitdepth functions.
+#else
+INSTANTIATE_TEST_CASE_P(
+    NEON, Loop8Test6Param,
+    ::testing::Values(
+#if HAVE_NEON_ASM
+// Using #if inside the macro is unsupported on MSVS but the tests are not
+// currently built for MSVS with ARM and NEON.
+        make_tuple(&vpx_lpf_horizontal_edge_8_neon,
+                   &vpx_lpf_horizontal_edge_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_16_neon,
+                   &vpx_lpf_horizontal_edge_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_neon,
+                   &vpx_lpf_vertical_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_dual_neon,
+                   &vpx_lpf_vertical_16_dual_c, 8),
+#endif  // HAVE_NEON_ASM
+        make_tuple(&vpx_lpf_horizontal_8_neon,
+                   &vpx_lpf_horizontal_8_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_neon,
+                   &vpx_lpf_vertical_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_4_neon,
+                   &vpx_lpf_horizontal_4_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_neon,
+                   &vpx_lpf_vertical_4_c, 8)));
+INSTANTIATE_TEST_CASE_P(
+    NEON, Loop8Test9Param,
+    ::testing::Values(
+#if HAVE_NEON_ASM
+        make_tuple(&vpx_lpf_horizontal_8_dual_neon,
+                   &vpx_lpf_horizontal_8_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_dual_neon,
+                   &vpx_lpf_vertical_8_dual_c, 8),
+#endif  // HAVE_NEON_ASM
+        make_tuple(&vpx_lpf_horizontal_4_dual_neon,
+                   &vpx_lpf_horizontal_4_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_dual_neon,
+                   &vpx_lpf_vertical_4_dual_c, 8)));
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+#endif  // HAVE_NEON
+
+#if HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+INSTANTIATE_TEST_CASE_P(
+    DSPR2, Loop8Test6Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_dspr2,
+                   &vpx_lpf_horizontal_4_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_dspr2,
+                   &vpx_lpf_horizontal_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_8,
+                   &vpx_lpf_horizontal_edge_8, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_16,
+                   &vpx_lpf_horizontal_edge_16, 8),
+        make_tuple(&vpx_lpf_vertical_4_dspr2,
+                   &vpx_lpf_vertical_4_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_dspr2,
+                   &vpx_lpf_vertical_8_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_dspr2,
+                   &vpx_lpf_vertical_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_dual_dspr2,
+                   &vpx_lpf_vertical_16_dual_c, 8)));
+
+INSTANTIATE_TEST_CASE_P(
+    DSPR2, Loop8Test9Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_dual_dspr2,
+                   &vpx_lpf_horizontal_4_dual_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_dual_dspr2,
+                   &vpx_lpf_horizontal_8_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_dual_dspr2,
+                   &vpx_lpf_vertical_4_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_dual_dspr2,
+                   &vpx_lpf_vertical_8_dual_c, 8)));
+#endif  // HAVE_DSPR2 && !CONFIG_VP9_HIGHBITDEPTH
+
+#if HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
+INSTANTIATE_TEST_CASE_P(
+    MSA, Loop8Test6Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_msa,
+                   &vpx_lpf_horizontal_4_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_msa,
+                   &vpx_lpf_horizontal_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_8_msa,
+                   &vpx_lpf_horizontal_edge_8_c, 8),
+        make_tuple(&vpx_lpf_horizontal_edge_16_msa,
+                   &vpx_lpf_horizontal_edge_16_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_msa,
+                   &vpx_lpf_vertical_4_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_msa,
+                   &vpx_lpf_vertical_8_c, 8),
+        make_tuple(&vpx_lpf_vertical_16_msa,
+                   &vpx_lpf_vertical_16_c, 8)));
+
+INSTANTIATE_TEST_CASE_P(
+    MSA, Loop8Test9Param,
+    ::testing::Values(
+        make_tuple(&vpx_lpf_horizontal_4_dual_msa,
+                   &vpx_lpf_horizontal_4_dual_c, 8),
+        make_tuple(&vpx_lpf_horizontal_8_dual_msa,
+                   &vpx_lpf_horizontal_8_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_4_dual_msa,
+                   &vpx_lpf_vertical_4_dual_c, 8),
+        make_tuple(&vpx_lpf_vertical_8_dual_msa,
+                   &vpx_lpf_vertical_8_dual_c, 8)));
+#endif  // HAVE_MSA && (!CONFIG_VP9_HIGHBITDEPTH)
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/md5_helper.h b/src/third_party/libvpx/test/md5_helper.h
new file mode 100644
index 0000000..742cf0b
--- /dev/null
+++ b/src/third_party/libvpx/test/md5_helper.h
@@ -0,0 +1,74 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_MD5_HELPER_H_
+#define TEST_MD5_HELPER_H_
+
+#include "./md5_utils.h"
+#include "vpx/vpx_decoder.h"
+
+namespace libvpx_test {
+class MD5 {
+ public:
+  MD5() {
+    MD5Init(&md5_);
+  }
+
+  void Add(const vpx_image_t *img) {
+    for (int plane = 0; plane < 3; ++plane) {
+      const uint8_t *buf = img->planes[plane];
+      // Calculate the width and height to do the md5 check. For the chroma
+      // plane, we never want to round down and thus skip a pixel so if
+      // we are shifting by 1 (chroma_shift) we add 1 before doing the shift.
+      // This works only for chroma_shift of 0 and 1.
+      const int bytes_per_sample =
+          (img->fmt & VPX_IMG_FMT_HIGHBITDEPTH) ? 2 : 1;
+      const int h = plane ? (img->d_h + img->y_chroma_shift) >>
+                    img->y_chroma_shift : img->d_h;
+      const int w = (plane ? (img->d_w + img->x_chroma_shift) >>
+                     img->x_chroma_shift : img->d_w) * bytes_per_sample;
+
+      for (int y = 0; y < h; ++y) {
+        MD5Update(&md5_, buf, w);
+        buf += img->stride[plane];
+      }
+    }
+  }
+
+  void Add(const uint8_t *data, size_t size) {
+    MD5Update(&md5_, data, static_cast<uint32_t>(size));
+  }
+
+  const char *Get(void) {
+    static const char hex[16] = {
+      '0', '1', '2', '3', '4', '5', '6', '7',
+      '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
+    };
+    uint8_t tmp[16];
+    MD5Context ctx_tmp = md5_;
+
+    MD5Final(tmp, &ctx_tmp);
+    for (int i = 0; i < 16; i++) {
+      res_[i * 2 + 0]  = hex[tmp[i] >> 4];
+      res_[i * 2 + 1]  = hex[tmp[i] & 0xf];
+    }
+    res_[32] = 0;
+
+    return res_;
+  }
+
+ protected:
+  char res_[33];
+  MD5Context md5_;
+};
+
+}  // namespace libvpx_test
+
+#endif  // TEST_MD5_HELPER_H_
diff --git a/src/third_party/libvpx/test/minmax_test.cc b/src/third_party/libvpx/test/minmax_test.cc
new file mode 100644
index 0000000..dbe4342
--- /dev/null
+++ b/src/third_party/libvpx/test/minmax_test.cc
@@ -0,0 +1,132 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "vpx/vpx_integer.h"
+
+#include "test/acm_random.h"
+#include "test/register_state_check.h"
+
+namespace {
+
+using ::libvpx_test::ACMRandom;
+
+typedef void (*MinMaxFunc)(const uint8_t *a, int a_stride,
+                           const uint8_t *b, int b_stride,
+                           int *min, int *max);
+
+class MinMaxTest : public ::testing::TestWithParam<MinMaxFunc> {
+ public:
+  virtual void SetUp() {
+    mm_func_ = GetParam();
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+ protected:
+  MinMaxFunc mm_func_;
+  ACMRandom rnd_;
+};
+
+void reference_minmax(const uint8_t *a, int a_stride,
+                      const uint8_t *b, int b_stride,
+                      int *min_ret, int *max_ret) {
+  int min = 255;
+  int max = 0;
+  for (int i = 0; i < 8; i++) {
+    for (int j = 0; j < 8; j++) {
+      const int diff = abs(a[i * a_stride + j] - b[i * b_stride + j]);
+      if (min > diff) min = diff;
+      if (max < diff) max = diff;
+    }
+  }
+
+  *min_ret = min;
+  *max_ret = max;
+}
+
+TEST_P(MinMaxTest, MinValue) {
+  for (int i = 0; i < 64; i++) {
+    uint8_t a[64], b[64];
+    memset(a, 0, sizeof(a));
+    memset(b, 255, sizeof(b));
+    b[i] = i;  // Set a minimum difference of i.
+
+    int min, max;
+    ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+    EXPECT_EQ(255, max);
+    EXPECT_EQ(i, min);
+  }
+}
+
+TEST_P(MinMaxTest, MaxValue) {
+  for (int i = 0; i < 64; i++) {
+    uint8_t a[64], b[64];
+    memset(a, 0, sizeof(a));
+    memset(b, 0, sizeof(b));
+    b[i] = i;  // Set a maximum difference of i.
+
+    int min, max;
+    ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+    EXPECT_EQ(i, max);
+    EXPECT_EQ(0, min);
+  }
+}
+
+TEST_P(MinMaxTest, CompareReference) {
+  uint8_t a[64], b[64];
+  for (int j = 0; j < 64; j++) {
+    a[j] = rnd_.Rand8();
+    b[j] = rnd_.Rand8();
+  }
+
+  int min_ref, max_ref, min, max;
+  reference_minmax(a, 8, b, 8, &min_ref, &max_ref);
+  ASM_REGISTER_STATE_CHECK(mm_func_(a, 8, b, 8, &min, &max));
+  EXPECT_EQ(max_ref, max);
+  EXPECT_EQ(min_ref, min);
+}
+
+TEST_P(MinMaxTest, CompareReferenceAndVaryStride) {
+  uint8_t a[8 * 64], b[8 * 64];
+  for (int i = 0; i < 8 * 64; i++) {
+    a[i] = rnd_.Rand8();
+    b[i] = rnd_.Rand8();
+  }
+  for (int a_stride = 8; a_stride <= 64; a_stride += 8) {
+    for (int b_stride = 8; b_stride <= 64; b_stride += 8) {
+      int min_ref, max_ref, min, max;
+      reference_minmax(a, a_stride, b, b_stride, &min_ref, &max_ref);
+      ASM_REGISTER_STATE_CHECK(mm_func_(a, a_stride, b, b_stride, &min, &max));
+      EXPECT_EQ(max_ref, max) << "when a_stride = " << a_stride
+                              << " and b_stride = " << b_stride;;
+      EXPECT_EQ(min_ref, min) << "when a_stride = " << a_stride
+                              << " and b_stride = " << b_stride;;
+    }
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(C, MinMaxTest, ::testing::Values(&vpx_minmax_8x8_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(SSE2, MinMaxTest,
+                        ::testing::Values(&vpx_minmax_8x8_sse2));
+#endif
+
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(NEON, MinMaxTest,
+                        ::testing::Values(&vpx_minmax_8x8_neon));
+#endif
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/partial_idct_test.cc b/src/third_party/libvpx/test/partial_idct_test.cc
new file mode 100644
index 0000000..6c82412
--- /dev/null
+++ b/src/third_party/libvpx/test/partial_idct_test.cc
@@ -0,0 +1,343 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vp9_rtcd.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp9/common/vp9_blockd.h"
+#include "vp9/common/vp9_scan.h"
+#include "vpx/vpx_integer.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+typedef void (*FwdTxfmFunc)(const int16_t *in, tran_low_t *out, int stride);
+typedef void (*InvTxfmFunc)(const tran_low_t *in, uint8_t *out, int stride);
+typedef std::tr1::tuple<FwdTxfmFunc,
+                        InvTxfmFunc,
+                        InvTxfmFunc,
+                        TX_SIZE, int> PartialInvTxfmParam;
+const int kMaxNumCoeffs = 1024;
+class PartialIDctTest : public ::testing::TestWithParam<PartialInvTxfmParam> {
+ public:
+  virtual ~PartialIDctTest() {}
+  virtual void SetUp() {
+    ftxfm_ = GET_PARAM(0);
+    full_itxfm_ = GET_PARAM(1);
+    partial_itxfm_ = GET_PARAM(2);
+    tx_size_  = GET_PARAM(3);
+    last_nonzero_ = GET_PARAM(4);
+  }
+
+  virtual void TearDown() { libvpx_test::ClearSystemState(); }
+
+ protected:
+  int last_nonzero_;
+  TX_SIZE tx_size_;
+  FwdTxfmFunc ftxfm_;
+  InvTxfmFunc full_itxfm_;
+  InvTxfmFunc partial_itxfm_;
+};
+
+TEST_P(PartialIDctTest, RunQuantCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  int size;
+  switch (tx_size_) {
+    case TX_4X4:
+      size = 4;
+      break;
+    case TX_8X8:
+      size = 8;
+      break;
+    case TX_16X16:
+      size = 16;
+      break;
+    case TX_32X32:
+      size = 32;
+      break;
+    default:
+      FAIL() << "Wrong Size!";
+      break;
+  }
+  DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
+
+  const int count_test_block = 1000;
+  const int block_size = size * size;
+
+  DECLARE_ALIGNED(16, int16_t, input_extreme_block[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, output_ref_block[kMaxNumCoeffs]);
+
+  int max_error = 0;
+  for (int i = 0; i < count_test_block; ++i) {
+    // clear out destination buffer
+    memset(dst1, 0, sizeof(*dst1) * block_size);
+    memset(dst2, 0, sizeof(*dst2) * block_size);
+    memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
+    memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
+
+    ACMRandom rnd(ACMRandom::DeterministicSeed());
+
+    for (int i = 0; i < count_test_block; ++i) {
+      // Initialize a test block with input range [-255, 255].
+      if (i == 0) {
+        for (int j = 0; j < block_size; ++j)
+          input_extreme_block[j] = 255;
+      } else if (i == 1) {
+        for (int j = 0; j < block_size; ++j)
+          input_extreme_block[j] = -255;
+      } else {
+        for (int j = 0; j < block_size; ++j) {
+          input_extreme_block[j] = rnd.Rand8() % 2 ? 255 : -255;
+        }
+      }
+
+      ftxfm_(input_extreme_block, output_ref_block, size);
+
+      // quantization with maximum allowed step sizes
+      test_coef_block1[0] = (output_ref_block[0] / 1336) * 1336;
+      for (int j = 1; j < last_nonzero_; ++j)
+        test_coef_block1[vp9_default_scan_orders[tx_size_].scan[j]]
+                         = (output_ref_block[j] / 1828) * 1828;
+    }
+
+    ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
+    ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block1, dst2, size));
+
+    for (int j = 0; j < block_size; ++j) {
+      const int diff = dst1[j] - dst2[j];
+      const int error = diff * diff;
+      if (max_error < error)
+        max_error = error;
+    }
+  }
+
+  EXPECT_EQ(0, max_error)
+      << "Error: partial inverse transform produces different results";
+}
+
+TEST_P(PartialIDctTest, ResultsMatch) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  int size;
+  switch (tx_size_) {
+    case TX_4X4:
+      size = 4;
+      break;
+    case TX_8X8:
+      size = 8;
+      break;
+    case TX_16X16:
+      size = 16;
+      break;
+    case TX_32X32:
+      size = 32;
+      break;
+    default:
+      FAIL() << "Wrong Size!";
+      break;
+  }
+  DECLARE_ALIGNED(16, tran_low_t, test_coef_block1[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, tran_low_t, test_coef_block2[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst1[kMaxNumCoeffs]);
+  DECLARE_ALIGNED(16, uint8_t, dst2[kMaxNumCoeffs]);
+  const int count_test_block = 1000;
+  const int max_coeff = 32766 / 4;
+  const int block_size = size * size;
+  int max_error = 0;
+  for (int i = 0; i < count_test_block; ++i) {
+    // clear out destination buffer
+    memset(dst1, 0, sizeof(*dst1) * block_size);
+    memset(dst2, 0, sizeof(*dst2) * block_size);
+    memset(test_coef_block1, 0, sizeof(*test_coef_block1) * block_size);
+    memset(test_coef_block2, 0, sizeof(*test_coef_block2) * block_size);
+    int max_energy_leftover = max_coeff * max_coeff;
+    for (int j = 0; j < last_nonzero_; ++j) {
+      int16_t coef = static_cast<int16_t>(sqrt(1.0 * max_energy_leftover) *
+                                          (rnd.Rand16() - 32768) / 65536);
+      max_energy_leftover -= coef * coef;
+      if (max_energy_leftover < 0) {
+        max_energy_leftover = 0;
+        coef = 0;
+      }
+      test_coef_block1[vp9_default_scan_orders[tx_size_].scan[j]] = coef;
+    }
+
+    memcpy(test_coef_block2, test_coef_block1,
+           sizeof(*test_coef_block2) * block_size);
+
+    ASM_REGISTER_STATE_CHECK(full_itxfm_(test_coef_block1, dst1, size));
+    ASM_REGISTER_STATE_CHECK(partial_itxfm_(test_coef_block2, dst2, size));
+
+    for (int j = 0; j < block_size; ++j) {
+      const int diff = dst1[j] - dst2[j];
+      const int error = diff * diff;
+      if (max_error < error)
+        max_error = error;
+    }
+  }
+
+  EXPECT_EQ(0, max_error)
+      << "Error: partial inverse transform produces different results";
+}
+using std::tr1::make_tuple;
+
+INSTANTIATE_TEST_CASE_P(
+    C, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_34_add_c,
+                   TX_32X32, 34),
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_1_add_c,
+                   TX_32X32, 1),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_10_add_c,
+                   TX_16X16, 10),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_1_add_c,
+                   TX_16X16, 1),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_12_add_c,
+                   TX_8X8, 12),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_1_add_c,
+                   TX_8X8, 1),
+        make_tuple(&vpx_fdct4x4_c,
+                   &vpx_idct4x4_16_add_c,
+                   &vpx_idct4x4_1_add_c,
+                   TX_4X4, 1)));
+
+#if HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    NEON, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_1_add_neon,
+                   TX_32X32, 1),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_10_add_neon,
+                   TX_16X16, 10),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_1_add_neon,
+                   TX_16X16, 1),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_12_add_neon,
+                   TX_8X8, 12),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_1_add_neon,
+                   TX_8X8, 1),
+        make_tuple(&vpx_fdct4x4_c,
+                   &vpx_idct4x4_16_add_c,
+                   &vpx_idct4x4_1_add_neon,
+                   TX_4X4, 1)));
+#endif  // HAVE_NEON && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+#if HAVE_SSE2 && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSE2, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_34_add_sse2,
+                   TX_32X32, 34),
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_1_add_sse2,
+                   TX_32X32, 1),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_10_add_sse2,
+                   TX_16X16, 10),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_1_add_sse2,
+                   TX_16X16, 1),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_12_add_sse2,
+                   TX_8X8, 12),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_1_add_sse2,
+                   TX_8X8, 1),
+        make_tuple(&vpx_fdct4x4_c,
+                   &vpx_idct4x4_16_add_c,
+                   &vpx_idct4x4_1_add_sse2,
+                   TX_4X4, 1)));
+#endif
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC && ARCH_X86_64 && \
+    !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    SSSE3_64, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_12_add_ssse3,
+                   TX_8X8, 12)));
+#endif
+
+#if HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+INSTANTIATE_TEST_CASE_P(
+    MSA, PartialIDctTest,
+    ::testing::Values(
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_34_add_msa,
+                   TX_32X32, 34),
+        make_tuple(&vpx_fdct32x32_c,
+                   &vpx_idct32x32_1024_add_c,
+                   &vpx_idct32x32_1_add_msa,
+                   TX_32X32, 1),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_10_add_msa,
+                   TX_16X16, 10),
+        make_tuple(&vpx_fdct16x16_c,
+                   &vpx_idct16x16_256_add_c,
+                   &vpx_idct16x16_1_add_msa,
+                   TX_16X16, 1),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_12_add_msa,
+                   TX_8X8, 10),
+        make_tuple(&vpx_fdct8x8_c,
+                   &vpx_idct8x8_64_add_c,
+                   &vpx_idct8x8_1_add_msa,
+                   TX_8X8, 1),
+        make_tuple(&vpx_fdct4x4_c,
+                   &vpx_idct4x4_16_add_c,
+                   &vpx_idct4x4_1_add_msa,
+                   TX_4X4, 1)));
+#endif  // HAVE_MSA && !CONFIG_VP9_HIGHBITDEPTH && !CONFIG_EMULATE_HARDWARE
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/postproc.sh b/src/third_party/libvpx/test/postproc.sh
new file mode 100755
index 0000000..939a3e7
--- /dev/null
+++ b/src/third_party/libvpx/test/postproc.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx postproc example code. To add new tests to this
+##  file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to postproc_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+#   $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+postproc_verify_environment() {
+  if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Runs postproc using $1 as input file. $2 is the codec name, and is used
+# solely to name the output file.
+postproc() {
+  local decoder="${LIBVPX_BIN_PATH}/postproc${VPX_TEST_EXE_SUFFIX}"
+  local input_file="$1"
+  local codec="$2"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/postproc_${codec}.raw"
+
+  if [ ! -x "${decoder}" ]; then
+    elog "${decoder} does not exist or is not executable."
+    return 1
+  fi
+
+  eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+      ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+}
+
+postproc_vp8() {
+  if [ "$(vp8_decode_available)" = "yes" ]; then
+    postproc "${VP8_IVF_FILE}" vp8 || return 1
+  fi
+}
+
+postproc_vp9() {
+  if [ "$(vpx_config_option_enabled CONFIG_VP9_POSTPROC)" = "yes" ]; then
+    if [ "$(vp9_decode_available)" = "yes" ]; then
+      postproc "${VP9_IVF_FILE}" vp9 || return 1
+    fi
+  fi
+}
+
+postproc_tests="postproc_vp8
+                postproc_vp9"
+
+run_tests postproc_verify_environment "${postproc_tests}"
diff --git a/src/third_party/libvpx/test/pp_filter_test.cc b/src/third_party/libvpx/test/pp_filter_test.cc
new file mode 100644
index 0000000..e4688dd
--- /dev/null
+++ b/src/third_party/libvpx/test/pp_filter_test.cc
@@ -0,0 +1,118 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "./vp8_rtcd.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+typedef void (*PostProcFunc)(unsigned char *src_ptr,
+                             unsigned char *dst_ptr,
+                             int src_pixels_per_line,
+                             int dst_pixels_per_line,
+                             int cols,
+                             unsigned char *flimit,
+                             int size);
+
+namespace {
+
+class VP8PostProcessingFilterTest
+    : public ::testing::TestWithParam<PostProcFunc> {
+ public:
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+};
+
+// Test routine for the VP8 post-processing function
+// vp8_post_proc_down_and_across_mb_row_c.
+
+TEST_P(VP8PostProcessingFilterTest, FilterOutputCheck) {
+  // Size of the underlying data block that will be filtered.
+  const int block_width  = 16;
+  const int block_height = 16;
+
+  // 5-tap filter needs 2 padding rows above and below the block in the input.
+  const int input_width = block_width;
+  const int input_height = block_height + 4;
+  const int input_stride = input_width;
+  const int input_size = input_width * input_height;
+
+  // Filter extends output block by 8 samples at left and right edges.
+  const int output_width = block_width + 16;
+  const int output_height = block_height;
+  const int output_stride = output_width;
+  const int output_size = output_width * output_height;
+
+  uint8_t *const src_image =
+      reinterpret_cast<uint8_t*>(vpx_calloc(input_size, 1));
+  uint8_t *const dst_image =
+      reinterpret_cast<uint8_t*>(vpx_calloc(output_size, 1));
+
+  // Pointers to top-left pixel of block in the input and output images.
+  uint8_t *const src_image_ptr = src_image + (input_stride << 1);
+  uint8_t *const dst_image_ptr = dst_image + 8;
+  uint8_t *const flimits =
+      reinterpret_cast<uint8_t *>(vpx_memalign(16, block_width));
+  (void)memset(flimits, 255, block_width);
+
+  // Initialize pixels in the input:
+  //   block pixels to value 1,
+  //   border pixels to value 10.
+  (void)memset(src_image, 10, input_size);
+  uint8_t *pixel_ptr = src_image_ptr;
+  for (int i = 0; i < block_height; ++i) {
+    for (int j = 0; j < block_width; ++j) {
+      pixel_ptr[j] = 1;
+    }
+    pixel_ptr += input_stride;
+  }
+
+  // Initialize pixels in the output to 99.
+  (void)memset(dst_image, 99, output_size);
+
+  ASM_REGISTER_STATE_CHECK(
+      GetParam()(src_image_ptr, dst_image_ptr, input_stride,
+                 output_stride, block_width, flimits, 16));
+
+  static const uint8_t expected_data[block_height] = {
+    4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 4
+  };
+
+  pixel_ptr = dst_image_ptr;
+  for (int i = 0; i < block_height; ++i) {
+    for (int j = 0; j < block_width; ++j) {
+      EXPECT_EQ(expected_data[i], pixel_ptr[j])
+          << "VP8PostProcessingFilterTest failed with invalid filter output";
+    }
+    pixel_ptr += output_stride;
+  }
+
+  vpx_free(src_image);
+  vpx_free(dst_image);
+  vpx_free(flimits);
+};
+
+INSTANTIATE_TEST_CASE_P(C, VP8PostProcessingFilterTest,
+    ::testing::Values(vp8_post_proc_down_and_across_mb_row_c));
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(SSE2, VP8PostProcessingFilterTest,
+    ::testing::Values(vp8_post_proc_down_and_across_mb_row_sse2));
+#endif
+
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(MSA, VP8PostProcessingFilterTest,
+    ::testing::Values(vp8_post_proc_down_and_across_mb_row_msa));
+#endif
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/quantize_test.cc b/src/third_party/libvpx/test/quantize_test.cc
new file mode 100644
index 0000000..69da899
--- /dev/null
+++ b/src/third_party/libvpx/test/quantize_test.cc
@@ -0,0 +1,203 @@
+/*
+ *  Copyright (c) 2014 The WebM 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 "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vp8_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vp8/common/blockd.h"
+#include "vp8/common/onyx.h"
+#include "vp8/encoder/block.h"
+#include "vp8/encoder/onyx_int.h"
+#include "vp8/encoder/quantize.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+const int kNumBlocks = 25;
+const int kNumBlockEntries = 16;
+
+typedef void (*VP8Quantize)(BLOCK *b, BLOCKD *d);
+
+typedef std::tr1::tuple<VP8Quantize, VP8Quantize> VP8QuantizeParam;
+
+using libvpx_test::ACMRandom;
+using std::tr1::make_tuple;
+
+// Create and populate a VP8_COMP instance which has a complete set of
+// quantization inputs as well as a second MACROBLOCKD for output.
+class QuantizeTestBase {
+ public:
+  virtual ~QuantizeTestBase() {
+    vp8_remove_compressor(&vp8_comp_);
+    vp8_comp_ = NULL;
+    vpx_free(macroblockd_dst_);
+    macroblockd_dst_ = NULL;
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  void SetupCompressor() {
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+
+    // The full configuration is necessary to generate the quantization tables.
+    VP8_CONFIG vp8_config;
+    memset(&vp8_config, 0, sizeof(vp8_config));
+
+    vp8_comp_ = vp8_create_compressor(&vp8_config);
+
+    // Set the tables based on a quantizer of 0.
+    vp8_set_quantizer(vp8_comp_, 0);
+
+    // Set up all the block/blockd pointers for the mb in vp8_comp_.
+    vp8cx_frame_init_quantizer(vp8_comp_);
+
+    // Copy macroblockd from the reference to get pre-set-up dequant values.
+    macroblockd_dst_ = reinterpret_cast<MACROBLOCKD *>(
+        vpx_memalign(32, sizeof(*macroblockd_dst_)));
+    memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
+    // Fix block pointers - currently they point to the blocks in the reference
+    // structure.
+    vp8_setup_block_dptrs(macroblockd_dst_);
+  }
+
+  void UpdateQuantizer(int q) {
+    vp8_set_quantizer(vp8_comp_, q);
+
+    memcpy(macroblockd_dst_, &vp8_comp_->mb.e_mbd, sizeof(*macroblockd_dst_));
+    vp8_setup_block_dptrs(macroblockd_dst_);
+  }
+
+  void FillCoeffConstant(int16_t c) {
+    for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
+      vp8_comp_->mb.coeff[i] = c;
+    }
+  }
+
+  void FillCoeffRandom() {
+    for (int i = 0; i < kNumBlocks * kNumBlockEntries; ++i) {
+      vp8_comp_->mb.coeff[i] = rnd_.Rand8();
+    }
+  }
+
+  void CheckOutput() {
+    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.qcoeff, macroblockd_dst_->qcoeff,
+                        sizeof(*macroblockd_dst_->qcoeff) * kNumBlocks *
+                            kNumBlockEntries))
+        << "qcoeff mismatch";
+    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.dqcoeff, macroblockd_dst_->dqcoeff,
+                        sizeof(*macroblockd_dst_->dqcoeff) * kNumBlocks *
+                            kNumBlockEntries))
+        << "dqcoeff mismatch";
+    EXPECT_EQ(0, memcmp(vp8_comp_->mb.e_mbd.eobs, macroblockd_dst_->eobs,
+                        sizeof(*macroblockd_dst_->eobs) * kNumBlocks))
+        << "eobs mismatch";
+  }
+
+  VP8_COMP *vp8_comp_;
+  MACROBLOCKD *macroblockd_dst_;
+
+ private:
+  ACMRandom rnd_;
+};
+
+class QuantizeTest : public QuantizeTestBase,
+                     public ::testing::TestWithParam<VP8QuantizeParam> {
+ protected:
+  virtual void SetUp() {
+    SetupCompressor();
+    asm_quant_ = GET_PARAM(0);
+    c_quant_ = GET_PARAM(1);
+  }
+
+  void RunComparison() {
+    for (int i = 0; i < kNumBlocks; ++i) {
+      ASM_REGISTER_STATE_CHECK(
+          c_quant_(&vp8_comp_->mb.block[i], &vp8_comp_->mb.e_mbd.block[i]));
+      ASM_REGISTER_STATE_CHECK(
+          asm_quant_(&vp8_comp_->mb.block[i], &macroblockd_dst_->block[i]));
+    }
+
+    CheckOutput();
+  }
+
+ private:
+  VP8Quantize asm_quant_;
+  VP8Quantize c_quant_;
+};
+
+TEST_P(QuantizeTest, TestZeroInput) {
+  FillCoeffConstant(0);
+  RunComparison();
+}
+
+TEST_P(QuantizeTest, TestLargeNegativeInput) {
+  FillCoeffConstant(0);
+  // Generate a qcoeff which contains 512/-512 (0x0100/0xFE00) to catch issues
+  // like BUG=883 where the constant being compared was incorrectly initialized.
+  vp8_comp_->mb.coeff[0] = -8191;
+  RunComparison();
+}
+
+TEST_P(QuantizeTest, TestRandomInput) {
+  FillCoeffRandom();
+  RunComparison();
+}
+
+TEST_P(QuantizeTest, TestMultipleQ) {
+  for (int q = 0; q < QINDEX_RANGE; ++q) {
+    UpdateQuantizer(q);
+    FillCoeffRandom();
+    RunComparison();
+  }
+}
+
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(
+    SSE2, QuantizeTest,
+    ::testing::Values(
+        make_tuple(&vp8_fast_quantize_b_sse2, &vp8_fast_quantize_b_c),
+        make_tuple(&vp8_regular_quantize_b_sse2, &vp8_regular_quantize_b_c)));
+#endif  // HAVE_SSE2
+
+#if HAVE_SSSE3
+INSTANTIATE_TEST_CASE_P(SSSE3, QuantizeTest,
+                        ::testing::Values(make_tuple(&vp8_fast_quantize_b_ssse3,
+                                                     &vp8_fast_quantize_b_c)));
+#endif  // HAVE_SSSE3
+
+#if HAVE_SSE4_1
+INSTANTIATE_TEST_CASE_P(
+    SSE4_1, QuantizeTest,
+    ::testing::Values(make_tuple(&vp8_regular_quantize_b_sse4_1,
+                                 &vp8_regular_quantize_b_c)));
+#endif  // HAVE_SSE4_1
+
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(NEON, QuantizeTest,
+                        ::testing::Values(make_tuple(&vp8_fast_quantize_b_neon,
+                                                     &vp8_fast_quantize_b_c)));
+#endif  // HAVE_NEON
+
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(
+    MSA, QuantizeTest,
+    ::testing::Values(
+        make_tuple(&vp8_fast_quantize_b_msa, &vp8_fast_quantize_b_c),
+        make_tuple(&vp8_regular_quantize_b_msa, &vp8_regular_quantize_b_c)));
+#endif  // HAVE_MSA
+}  // namespace
diff --git a/src/third_party/libvpx/test/realtime_test.cc b/src/third_party/libvpx/test/realtime_test.cc
new file mode 100644
index 0000000..24749e4
--- /dev/null
+++ b/src/third_party/libvpx/test/realtime_test.cc
@@ -0,0 +1,64 @@
+/*
+ *  Copyright (c) 2016 The WebM 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 "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/util.h"
+#include "test/video_source.h"
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+namespace {
+
+const int kVideoSourceWidth = 320;
+const int kVideoSourceHeight = 240;
+const int kFramesToEncode = 2;
+
+class RealtimeTest
+    : public ::libvpx_test::EncoderTest,
+      public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  RealtimeTest()
+      : EncoderTest(GET_PARAM(0)), frame_packets_(0) {}
+  virtual ~RealtimeTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    cfg_.g_lag_in_frames = 0;
+    SetMode(::libvpx_test::kRealTime);
+  }
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+    // TODO(tomfinegan): We're changing the pass value here to make sure
+    // we get frames when real time mode is combined with |g_pass| set to
+    // VPX_RC_FIRST_PASS. This is necessary because EncoderTest::RunLoop() sets
+    // the pass value based on the mode passed into EncoderTest::SetMode(),
+    // which overrides the one specified in SetUp() above.
+    cfg_.g_pass = VPX_RC_FIRST_PASS;
+  }
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t * /*pkt*/) {
+    frame_packets_++;
+  }
+
+  int frame_packets_;
+};
+
+TEST_P(RealtimeTest, RealtimeFirstPassProducesFrames) {
+  ::libvpx_test::RandomVideoSource video;
+  video.SetSize(kVideoSourceWidth, kVideoSourceHeight);
+  video.set_limit(kFramesToEncode);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  EXPECT_EQ(kFramesToEncode, frame_packets_);
+}
+
+VP8_INSTANTIATE_TEST_CASE(RealtimeTest,
+                          ::testing::Values(::libvpx_test::kRealTime));
+VP9_INSTANTIATE_TEST_CASE(RealtimeTest,
+                          ::testing::Values(::libvpx_test::kRealTime));
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/register_state_check.h b/src/third_party/libvpx/test/register_state_check.h
new file mode 100644
index 0000000..5336f2f
--- /dev/null
+++ b/src/third_party/libvpx/test/register_state_check.h
@@ -0,0 +1,192 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 TEST_REGISTER_STATE_CHECK_H_
+#define TEST_REGISTER_STATE_CHECK_H_
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "./vpx_config.h"
+#include "vpx/vpx_integer.h"
+
+// ASM_REGISTER_STATE_CHECK(asm_function)
+//   Minimally validates the environment pre & post function execution. This
+//   variant should be used with assembly functions which are not expected to
+//   fully restore the system state. See platform implementations of
+//   RegisterStateCheck for details.
+//
+// API_REGISTER_STATE_CHECK(api_function)
+//   Performs all the checks done by ASM_REGISTER_STATE_CHECK() and any
+//   additional checks to ensure the environment is in a consistent state pre &
+//   post function execution. This variant should be used with API functions.
+//   See platform implementations of RegisterStateCheckXXX for details.
+//
+
+#if defined(_WIN64)
+
+#undef NOMINMAX
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <winnt.h>
+
+inline bool operator==(const M128A& lhs, const M128A& rhs) {
+  return (lhs.Low == rhs.Low && lhs.High == rhs.High);
+}
+
+namespace libvpx_test {
+
+// Compares the state of xmm[6-15] at construction with their state at
+// destruction. These registers should be preserved by the callee on
+// Windows x64.
+class RegisterStateCheck {
+ public:
+  RegisterStateCheck() { initialized_ = StoreRegisters(&pre_context_); }
+  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
+
+ private:
+  static bool StoreRegisters(CONTEXT* const context) {
+    const HANDLE this_thread = GetCurrentThread();
+    EXPECT_TRUE(this_thread != NULL);
+    context->ContextFlags = CONTEXT_FLOATING_POINT;
+    const bool context_saved = GetThreadContext(this_thread, context) == TRUE;
+    EXPECT_TRUE(context_saved) << "GetLastError: " << GetLastError();
+    return context_saved;
+  }
+
+  // Compares the register state. Returns true if the states match.
+  bool Check() const {
+    if (!initialized_) return false;
+    CONTEXT post_context;
+    if (!StoreRegisters(&post_context)) return false;
+
+    const M128A* xmm_pre = &pre_context_.Xmm6;
+    const M128A* xmm_post = &post_context.Xmm6;
+    for (int i = 6; i <= 15; ++i) {
+      EXPECT_EQ(*xmm_pre, *xmm_post) << "xmm" << i << " has been modified!";
+      ++xmm_pre;
+      ++xmm_post;
+    }
+    return !testing::Test::HasNonfatalFailure();
+  }
+
+  bool initialized_;
+  CONTEXT pre_context_;
+};
+
+#define ASM_REGISTER_STATE_CHECK(statement) do {  \
+  libvpx_test::RegisterStateCheck reg_check;      \
+  statement;                                      \
+} while (false)
+
+}  // namespace libvpx_test
+
+#elif defined(CONFIG_SHARED) && defined(HAVE_NEON_ASM) && defined(CONFIG_VP9) \
+      && !CONFIG_SHARED && HAVE_NEON_ASM && CONFIG_VP9
+
+extern "C" {
+// Save the d8-d15 registers into store.
+void vpx_push_neon(int64_t *store);
+}
+
+namespace libvpx_test {
+
+// Compares the state of d8-d15 at construction with their state at
+// destruction. These registers should be preserved by the callee on
+// arm platform.
+class RegisterStateCheck {
+ public:
+  RegisterStateCheck() { initialized_ = StoreRegisters(pre_store_); }
+  ~RegisterStateCheck() { EXPECT_TRUE(Check()); }
+
+ private:
+  static bool StoreRegisters(int64_t store[8]) {
+    vpx_push_neon(store);
+    return true;
+  }
+
+  // Compares the register state. Returns true if the states match.
+  bool Check() const {
+    if (!initialized_) return false;
+    int64_t post_store[8];
+    vpx_push_neon(post_store);
+    for (int i = 0; i < 8; ++i) {
+      EXPECT_EQ(pre_store_[i], post_store[i]) << "d"
+          << i + 8 << " has been modified";
+    }
+    return !testing::Test::HasNonfatalFailure();
+  }
+
+  bool initialized_;
+  int64_t pre_store_[8];
+};
+
+#define ASM_REGISTER_STATE_CHECK(statement) do {  \
+  libvpx_test::RegisterStateCheck reg_check;      \
+  statement;                                      \
+} while (false)
+
+}  // namespace libvpx_test
+
+#else
+
+namespace libvpx_test {
+
+class RegisterStateCheck {};
+#define ASM_REGISTER_STATE_CHECK(statement) statement
+
+}  // namespace libvpx_test
+
+#endif  // _WIN64
+
+#if ARCH_X86 || ARCH_X86_64
+#if defined(__GNUC__)
+
+namespace libvpx_test {
+
+// Checks the FPU tag word pre/post execution to ensure emms has been called.
+class RegisterStateCheckMMX {
+ public:
+  RegisterStateCheckMMX() {
+    __asm__ volatile("fstenv %0" : "=rm"(pre_fpu_env_));
+  }
+  ~RegisterStateCheckMMX() { EXPECT_TRUE(Check()); }
+
+ private:
+  // Checks the FPU tag word pre/post execution, returning false if not cleared
+  // to 0xffff.
+  bool Check() const {
+    EXPECT_EQ(0xffff, pre_fpu_env_[4])
+        << "FPU was in an inconsistent state prior to call";
+
+    uint16_t post_fpu_env[14];
+    __asm__ volatile("fstenv %0" : "=rm"(post_fpu_env));
+    EXPECT_EQ(0xffff, post_fpu_env[4])
+        << "FPU was left in an inconsistent state after call";
+    return !testing::Test::HasNonfatalFailure();
+  }
+
+  uint16_t pre_fpu_env_[14];
+};
+
+#define API_REGISTER_STATE_CHECK(statement) do {  \
+  libvpx_test::RegisterStateCheckMMX reg_check;   \
+  ASM_REGISTER_STATE_CHECK(statement);            \
+} while (false)
+
+}  // namespace libvpx_test
+
+#endif  // __GNUC__
+#endif  // ARCH_X86 || ARCH_X86_64
+
+#ifndef API_REGISTER_STATE_CHECK
+#define API_REGISTER_STATE_CHECK ASM_REGISTER_STATE_CHECK
+#endif
+
+#endif  // TEST_REGISTER_STATE_CHECK_H_
diff --git a/src/third_party/libvpx/test/resize_test.cc b/src/third_party/libvpx/test/resize_test.cc
new file mode 100644
index 0000000..90f5452
--- /dev/null
+++ b/src/third_party/libvpx/test/resize_test.cc
@@ -0,0 +1,735 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <climits>
+#include <vector>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/video_source.h"
+#include "test/util.h"
+
+// Enable(1) or Disable(0) writing of the compressed bitstream.
+#define WRITE_COMPRESSED_STREAM 0
+
+namespace {
+
+#if WRITE_COMPRESSED_STREAM
+static void mem_put_le16(char *const mem, const unsigned int val) {
+  mem[0] = val;
+  mem[1] = val >> 8;
+}
+
+static void mem_put_le32(char *const mem, const unsigned int val) {
+  mem[0] = val;
+  mem[1] = val >> 8;
+  mem[2] = val >> 16;
+  mem[3] = val >> 24;
+}
+
+static void write_ivf_file_header(const vpx_codec_enc_cfg_t *const cfg,
+                                  int frame_cnt, FILE *const outfile) {
+  char header[32];
+
+  header[0] = 'D';
+  header[1] = 'K';
+  header[2] = 'I';
+  header[3] = 'F';
+  mem_put_le16(header + 4,  0);                   /* version */
+  mem_put_le16(header + 6,  32);                  /* headersize */
+  mem_put_le32(header + 8,  0x30395056);          /* fourcc (vp9) */
+  mem_put_le16(header + 12, cfg->g_w);            /* width */
+  mem_put_le16(header + 14, cfg->g_h);            /* height */
+  mem_put_le32(header + 16, cfg->g_timebase.den); /* rate */
+  mem_put_le32(header + 20, cfg->g_timebase.num); /* scale */
+  mem_put_le32(header + 24, frame_cnt);           /* length */
+  mem_put_le32(header + 28, 0);                   /* unused */
+
+  (void)fwrite(header, 1, 32, outfile);
+}
+
+static void write_ivf_frame_size(FILE *const outfile, const size_t size) {
+  char header[4];
+  mem_put_le32(header, static_cast<unsigned int>(size));
+  (void)fwrite(header, 1, 4, outfile);
+}
+
+static void write_ivf_frame_header(const vpx_codec_cx_pkt_t *const pkt,
+                                   FILE *const outfile) {
+  char header[12];
+  vpx_codec_pts_t pts;
+
+  if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+    return;
+
+  pts = pkt->data.frame.pts;
+  mem_put_le32(header, static_cast<unsigned int>(pkt->data.frame.sz));
+  mem_put_le32(header + 4, pts & 0xFFFFFFFF);
+  mem_put_le32(header + 8, pts >> 32);
+
+  (void)fwrite(header, 1, 12, outfile);
+}
+#endif  // WRITE_COMPRESSED_STREAM
+
+const unsigned int kInitialWidth = 320;
+const unsigned int kInitialHeight = 240;
+
+struct FrameInfo {
+  FrameInfo(vpx_codec_pts_t _pts, unsigned int _w, unsigned int _h)
+      : pts(_pts), w(_w), h(_h) {}
+
+  vpx_codec_pts_t pts;
+  unsigned int w;
+  unsigned int h;
+};
+
+void ScaleForFrameNumber(unsigned int frame,
+                         unsigned int initial_w,
+                         unsigned int initial_h,
+                         unsigned int *w,
+                         unsigned int *h,
+                         int flag_codec) {
+  if (frame < 10) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 20) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 30) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 40) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 50) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 60) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 70) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 80) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 90) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 100) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 110) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 120) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 130) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 140) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 150) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 160) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 170) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 180) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 190) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 200) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 210) {
+    *w = initial_w / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 220) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 230) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  if (frame < 240) {
+    *w = initial_w * 3 / 4;
+    *h = initial_h * 3 / 4;
+    return;
+  }
+  if (frame < 250) {
+    *w = initial_w  / 2;
+    *h = initial_h / 2;
+    return;
+  }
+  if (frame < 260) {
+    *w = initial_w;
+    *h = initial_h;
+    return;
+  }
+  // Go down very low.
+  if (frame < 270) {
+    *w = initial_w / 4;
+    *h = initial_h / 4;
+    return;
+  }
+  if (flag_codec == 1) {
+    // Cases that only works for VP9.
+    // For VP9: Swap width and height of original.
+    if (frame < 320) {
+      *w = initial_h;
+      *h = initial_w;
+      return;
+    }
+  }
+  *w = initial_w;
+  *h = initial_h;
+}
+
+class ResizingVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+  ResizingVideoSource() {
+    SetSize(kInitialWidth, kInitialHeight);
+    limit_ = 350;
+  }
+  int flag_codec_;
+  virtual ~ResizingVideoSource() {}
+
+ protected:
+  virtual void Next() {
+    ++frame_;
+    unsigned int width;
+    unsigned int height;
+    ScaleForFrameNumber(frame_, kInitialWidth, kInitialHeight, &width, &height,
+                        flag_codec_);
+    SetSize(width, height);
+    FillFrame();
+  }
+};
+
+class ResizeTest : public ::libvpx_test::EncoderTest,
+  public ::libvpx_test::CodecTestWithParam<libvpx_test::TestMode> {
+ protected:
+  ResizeTest() : EncoderTest(GET_PARAM(0)) {}
+
+  virtual ~ResizeTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t &img,
+                                     vpx_codec_pts_t pts) {
+    frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
+  }
+
+  std::vector< FrameInfo > frame_info_list_;
+};
+
+TEST_P(ResizeTest, TestExternalResizeWorks) {
+  ResizingVideoSource video;
+  video.flag_codec_ = 0;
+  cfg_.g_lag_in_frames = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    const unsigned int frame = static_cast<unsigned>(info->pts);
+    unsigned int expected_w;
+    unsigned int expected_h;
+    ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
+                        &expected_w, &expected_h, 0);
+    EXPECT_EQ(expected_w, info->w)
+        << "Frame " << frame << " had unexpected width";
+    EXPECT_EQ(expected_h, info->h)
+        << "Frame " << frame << " had unexpected height";
+  }
+}
+
+const unsigned int kStepDownFrame = 3;
+const unsigned int kStepUpFrame = 6;
+
+class ResizeInternalTest : public ResizeTest {
+ protected:
+#if WRITE_COMPRESSED_STREAM
+  ResizeInternalTest()
+      : ResizeTest(),
+        frame0_psnr_(0.0),
+        outfile_(NULL),
+        out_frames_(0) {}
+#else
+  ResizeInternalTest() : ResizeTest(), frame0_psnr_(0.0) {}
+#endif
+
+  virtual ~ResizeInternalTest() {}
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+#if WRITE_COMPRESSED_STREAM
+    outfile_ = fopen("vp90-2-05-resize.ivf", "wb");
+#endif
+  }
+
+  virtual void EndPassHook() {
+#if WRITE_COMPRESSED_STREAM
+    if (outfile_) {
+      if (!fseek(outfile_, 0, SEEK_SET))
+        write_ivf_file_header(&cfg_, out_frames_, outfile_);
+      fclose(outfile_);
+      outfile_ = NULL;
+    }
+#endif
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (change_config_) {
+      int new_q = 60;
+      if (video->frame() == 0) {
+        struct vpx_scaling_mode mode = {VP8E_ONETWO, VP8E_ONETWO};
+        encoder->Control(VP8E_SET_SCALEMODE, &mode);
+      }
+      if (video->frame() == 1) {
+        struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
+        encoder->Control(VP8E_SET_SCALEMODE, &mode);
+        cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = new_q;
+        encoder->Config(&cfg_);
+      }
+    } else {
+      if (video->frame() == kStepDownFrame) {
+        struct vpx_scaling_mode mode = {VP8E_FOURFIVE, VP8E_THREEFIVE};
+        encoder->Control(VP8E_SET_SCALEMODE, &mode);
+      }
+      if (video->frame() == kStepUpFrame) {
+        struct vpx_scaling_mode mode = {VP8E_NORMAL, VP8E_NORMAL};
+        encoder->Control(VP8E_SET_SCALEMODE, &mode);
+      }
+    }
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (!frame0_psnr_)
+      frame0_psnr_ = pkt->data.psnr.psnr[0];
+    EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
+  }
+
+#if WRITE_COMPRESSED_STREAM
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    ++out_frames_;
+
+    // Write initial file header if first frame.
+    if (pkt->data.frame.pts == 0)
+      write_ivf_file_header(&cfg_, 0, outfile_);
+
+    // Write frame header and data.
+    write_ivf_frame_header(pkt, outfile_);
+    (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
+  }
+#endif
+
+  double frame0_psnr_;
+  bool change_config_;
+#if WRITE_COMPRESSED_STREAM
+  FILE *outfile_;
+  unsigned int out_frames_;
+#endif
+};
+
+TEST_P(ResizeInternalTest, TestInternalResizeWorks) {
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 10);
+  init_flags_ = VPX_CODEC_USE_PSNR;
+  change_config_ = false;
+
+  // q picked such that initial keyframe on this clip is ~30dB PSNR
+  cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
+
+  // If the number of frames being encoded is smaller than g_lag_in_frames
+  // the encoded frame is unavailable using the current API. Comparing
+  // frames to detect mismatch would then not be possible. Set
+  // g_lag_in_frames = 0 to get around this.
+  cfg_.g_lag_in_frames = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    const vpx_codec_pts_t pts = info->pts;
+    if (pts >= kStepDownFrame && pts < kStepUpFrame) {
+      ASSERT_EQ(282U, info->w) << "Frame " << pts << " had unexpected width";
+      ASSERT_EQ(173U, info->h) << "Frame " << pts << " had unexpected height";
+    } else {
+      EXPECT_EQ(352U, info->w) << "Frame " << pts << " had unexpected width";
+      EXPECT_EQ(288U, info->h) << "Frame " << pts << " had unexpected height";
+    }
+  }
+}
+
+TEST_P(ResizeInternalTest, TestInternalResizeChangeConfig) {
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 10);
+  cfg_.g_w = 352;
+  cfg_.g_h = 288;
+  change_config_ = true;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+class ResizeRealtimeTest : public ::libvpx_test::EncoderTest,
+  public ::libvpx_test::CodecTestWith2Params<libvpx_test::TestMode, int> {
+ protected:
+  ResizeRealtimeTest() : EncoderTest(GET_PARAM(0)) {}
+  virtual ~ResizeRealtimeTest() {}
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (video->frame() == 0) {
+      encoder->Control(VP9E_SET_AQ_MODE, 3);
+      encoder->Control(VP8E_SET_CPUUSED, set_cpu_used_);
+    }
+
+    if (change_bitrate_ && video->frame() == 120) {
+      change_bitrate_ = false;
+      cfg_.rc_target_bitrate = 500;
+      encoder->Config(&cfg_);
+    }
+  }
+
+  virtual void SetUp() {
+    InitializeConfig();
+    SetMode(GET_PARAM(1));
+    set_cpu_used_ = GET_PARAM(2);
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t &img,
+                                     vpx_codec_pts_t pts) {
+    frame_info_list_.push_back(FrameInfo(pts, img.d_w, img.d_h));
+  }
+
+  virtual void MismatchHook(const vpx_image_t *img1,
+                             const vpx_image_t *img2) {
+    double mismatch_psnr = compute_psnr(img1, img2);
+    mismatch_psnr_ += mismatch_psnr;
+    ++mismatch_nframes_;
+  }
+
+  unsigned int GetMismatchFrames() {
+      return mismatch_nframes_;
+  }
+
+  void DefaultConfig() {
+    cfg_.rc_buf_initial_sz = 500;
+    cfg_.rc_buf_optimal_sz = 600;
+    cfg_.rc_buf_sz = 1000;
+    cfg_.rc_min_quantizer = 2;
+    cfg_.rc_max_quantizer = 56;
+    cfg_.rc_undershoot_pct = 50;
+    cfg_.rc_overshoot_pct = 50;
+    cfg_.rc_end_usage = VPX_CBR;
+    cfg_.kf_mode = VPX_KF_AUTO;
+    cfg_.g_lag_in_frames = 0;
+    cfg_.kf_min_dist = cfg_.kf_max_dist = 3000;
+    // Enable dropped frames.
+    cfg_.rc_dropframe_thresh = 1;
+    // Enable error_resilience mode.
+    cfg_.g_error_resilient  = 1;
+    // Enable dynamic resizing.
+    cfg_.rc_resize_allowed = 1;
+    // Run at low bitrate.
+    cfg_.rc_target_bitrate = 200;
+  }
+
+  std::vector< FrameInfo > frame_info_list_;
+  int set_cpu_used_;
+  bool change_bitrate_;
+  double mismatch_psnr_;
+  int mismatch_nframes_;
+};
+
+TEST_P(ResizeRealtimeTest, TestExternalResizeWorks) {
+  ResizingVideoSource video;
+  video.flag_codec_ = 1;
+  DefaultConfig();
+  // Disable internal resize for this test.
+  cfg_.rc_resize_allowed = 0;
+  change_bitrate_ = false;
+  mismatch_psnr_ = 0.0;
+  mismatch_nframes_ = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    const unsigned int frame = static_cast<unsigned>(info->pts);
+    unsigned int expected_w;
+    unsigned int expected_h;
+    ScaleForFrameNumber(frame, kInitialWidth, kInitialHeight,
+                        &expected_w, &expected_h, 1);
+    EXPECT_EQ(expected_w, info->w)
+        << "Frame " << frame << " had unexpected width";
+    EXPECT_EQ(expected_h, info->h)
+        << "Frame " << frame << " had unexpected height";
+    EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+  }
+}
+
+// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
+// Run at low bitrate, with resize_allowed = 1, and verify that we get
+// one resize down event.
+TEST_P(ResizeRealtimeTest, TestInternalResizeDown) {
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 299);
+  DefaultConfig();
+  cfg_.g_w = 352;
+  cfg_.g_h = 288;
+  change_bitrate_ = false;
+  mismatch_psnr_ = 0.0;
+  mismatch_nframes_ = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  unsigned int last_w = cfg_.g_w;
+  unsigned int last_h = cfg_.g_h;
+  int resize_count = 0;
+  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    if (info->w != last_w || info->h != last_h) {
+      // Verify that resize down occurs.
+      ASSERT_LT(info->w, last_w);
+      ASSERT_LT(info->h, last_h);
+      last_w = info->w;
+      last_h = info->h;
+      resize_count++;
+    }
+  }
+
+#if CONFIG_VP9_DECODER
+  // Verify that we get 1 resize down event in this test.
+  ASSERT_EQ(1, resize_count) << "Resizing should occur.";
+  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+#else
+  printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
+#endif
+}
+
+// Verify the dynamic resizer behavior for real time, 1 pass CBR mode.
+// Start at low target bitrate, raise the bitrate in the middle of the clip,
+// scaling-up should occur after bitrate changed.
+TEST_P(ResizeRealtimeTest, TestInternalResizeDownUpChangeBitRate) {
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 359);
+  DefaultConfig();
+  cfg_.g_w = 352;
+  cfg_.g_h = 288;
+  change_bitrate_ = true;
+  mismatch_psnr_ = 0.0;
+  mismatch_nframes_ = 0;
+  // Disable dropped frames.
+  cfg_.rc_dropframe_thresh = 0;
+  // Starting bitrate low.
+  cfg_.rc_target_bitrate = 80;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+
+  unsigned int last_w = cfg_.g_w;
+  unsigned int last_h = cfg_.g_h;
+  int resize_count = 0;
+  for (std::vector<FrameInfo>::const_iterator info = frame_info_list_.begin();
+       info != frame_info_list_.end(); ++info) {
+    if (info->w != last_w || info->h != last_h) {
+      resize_count++;
+      if (resize_count == 1) {
+        // Verify that resize down occurs.
+        ASSERT_LT(info->w, last_w);
+        ASSERT_LT(info->h, last_h);
+      } else if (resize_count == 2) {
+        // Verify that resize up occurs.
+        ASSERT_GT(info->w, last_w);
+        ASSERT_GT(info->h, last_h);
+      }
+      last_w = info->w;
+      last_h = info->h;
+    }
+  }
+
+#if CONFIG_VP9_DECODER
+  // Verify that we get 2 resize events in this test.
+  ASSERT_EQ(resize_count, 2) << "Resizing should occur twice.";
+  EXPECT_EQ(static_cast<unsigned int>(0), GetMismatchFrames());
+#else
+  printf("Warning: VP9 decoder unavailable, unable to check resize count!\n");
+#endif
+}
+
+vpx_img_fmt_t CspForFrameNumber(int frame) {
+  if (frame < 10)
+    return VPX_IMG_FMT_I420;
+  if (frame < 20)
+    return VPX_IMG_FMT_I444;
+  return VPX_IMG_FMT_I420;
+}
+
+class ResizeCspTest : public ResizeTest {
+ protected:
+#if WRITE_COMPRESSED_STREAM
+  ResizeCspTest()
+      : ResizeTest(),
+        frame0_psnr_(0.0),
+        outfile_(NULL),
+        out_frames_(0) {}
+#else
+  ResizeCspTest() : ResizeTest(), frame0_psnr_(0.0) {}
+#endif
+
+  virtual ~ResizeCspTest() {}
+
+  virtual void BeginPassHook(unsigned int /*pass*/) {
+#if WRITE_COMPRESSED_STREAM
+    outfile_ = fopen("vp91-2-05-cspchape.ivf", "wb");
+#endif
+  }
+
+  virtual void EndPassHook() {
+#if WRITE_COMPRESSED_STREAM
+    if (outfile_) {
+      if (!fseek(outfile_, 0, SEEK_SET))
+        write_ivf_file_header(&cfg_, out_frames_, outfile_);
+      fclose(outfile_);
+      outfile_ = NULL;
+    }
+#endif
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (CspForFrameNumber(video->frame()) != VPX_IMG_FMT_I420 &&
+        cfg_.g_profile != 1) {
+      cfg_.g_profile = 1;
+      encoder->Config(&cfg_);
+    }
+    if (CspForFrameNumber(video->frame()) == VPX_IMG_FMT_I420 &&
+        cfg_.g_profile != 0) {
+      cfg_.g_profile = 0;
+      encoder->Config(&cfg_);
+    }
+  }
+
+  virtual void PSNRPktHook(const vpx_codec_cx_pkt_t *pkt) {
+    if (!frame0_psnr_)
+      frame0_psnr_ = pkt->data.psnr.psnr[0];
+    EXPECT_NEAR(pkt->data.psnr.psnr[0], frame0_psnr_, 2.0);
+  }
+
+#if WRITE_COMPRESSED_STREAM
+  virtual void FramePktHook(const vpx_codec_cx_pkt_t *pkt) {
+    ++out_frames_;
+
+    // Write initial file header if first frame.
+    if (pkt->data.frame.pts == 0)
+      write_ivf_file_header(&cfg_, 0, outfile_);
+
+    // Write frame header and data.
+    write_ivf_frame_header(pkt, outfile_);
+    (void)fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz, outfile_);
+  }
+#endif
+
+  double frame0_psnr_;
+#if WRITE_COMPRESSED_STREAM
+  FILE *outfile_;
+  unsigned int out_frames_;
+#endif
+};
+
+class ResizingCspVideoSource : public ::libvpx_test::DummyVideoSource {
+ public:
+  ResizingCspVideoSource() {
+    SetSize(kInitialWidth, kInitialHeight);
+    limit_ = 30;
+  }
+
+  virtual ~ResizingCspVideoSource() {}
+
+ protected:
+  virtual void Next() {
+    ++frame_;
+    SetImageFormat(CspForFrameNumber(frame_));
+    FillFrame();
+  }
+};
+
+TEST_P(ResizeCspTest, TestResizeCspWorks) {
+  ResizingCspVideoSource video;
+  init_flags_ = VPX_CODEC_USE_PSNR;
+  cfg_.rc_min_quantizer = cfg_.rc_max_quantizer = 48;
+  cfg_.g_lag_in_frames = 0;
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+}
+
+VP8_INSTANTIATE_TEST_CASE(ResizeTest, ONE_PASS_TEST_MODES);
+VP9_INSTANTIATE_TEST_CASE(ResizeTest,
+                          ::testing::Values(::libvpx_test::kRealTime));
+VP9_INSTANTIATE_TEST_CASE(ResizeInternalTest,
+                          ::testing::Values(::libvpx_test::kOnePassBest));
+VP9_INSTANTIATE_TEST_CASE(ResizeRealtimeTest,
+                          ::testing::Values(::libvpx_test::kRealTime),
+                          ::testing::Range(5, 9));
+VP9_INSTANTIATE_TEST_CASE(ResizeCspTest,
+                          ::testing::Values(::libvpx_test::kRealTime));
+}  // namespace
diff --git a/src/third_party/libvpx/test/resize_util.sh b/src/third_party/libvpx/test/resize_util.sh
new file mode 100755
index 0000000..5e47271
--- /dev/null
+++ b/src/third_party/libvpx/test/resize_util.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx resize_util example code. To add new tests to
+##  this file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to resize_util_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+resize_util_verify_environment() {
+  if [ ! -e "${YUV_RAW_INPUT}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Resizes $YUV_RAW_INPUT using the resize_util example. $1 is the output
+# dimensions that will be passed to resize_util.
+resize_util() {
+  local resizer="${LIBVPX_BIN_PATH}/resize_util${VPX_TEST_EXE_SUFFIX}"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/resize_util.raw"
+  local frames_to_resize="10"
+  local target_dimensions="$1"
+
+  # resize_util is available only when CONFIG_SHARED is disabled.
+  if [ -z "$(vpx_config_option_enabled CONFIG_SHARED)" ]; then
+    if [ ! -x "${resizer}" ]; then
+      elog "${resizer} does not exist or is not executable."
+      return 1
+    fi
+
+    eval "${VPX_TEST_PREFIX}" "${resizer}" "${YUV_RAW_INPUT}" \
+        "${YUV_RAW_INPUT_WIDTH}x${YUV_RAW_INPUT_HEIGHT}" \
+        "${target_dimensions}" "${output_file}" ${frames_to_resize} \
+        ${devnull}
+
+    [ -e "${output_file}" ] || return 1
+  fi
+}
+
+# Halves each dimension of $YUV_RAW_INPUT using resize_util().
+resize_down() {
+  local target_width=$((${YUV_RAW_INPUT_WIDTH} / 2))
+  local target_height=$((${YUV_RAW_INPUT_HEIGHT} / 2))
+
+  resize_util "${target_width}x${target_height}"
+}
+
+# Doubles each dimension of $YUV_RAW_INPUT using resize_util().
+resize_up() {
+  local target_width=$((${YUV_RAW_INPUT_WIDTH} * 2))
+  local target_height=$((${YUV_RAW_INPUT_HEIGHT} * 2))
+
+  resize_util "${target_width}x${target_height}"
+}
+
+resize_util_tests="resize_down
+                   resize_up"
+
+run_tests resize_util_verify_environment "${resize_util_tests}"
diff --git a/src/third_party/libvpx/test/sad_test.cc b/src/third_party/libvpx/test/sad_test.cc
new file mode 100644
index 0000000..e6bd0d7
--- /dev/null
+++ b/src/third_party/libvpx/test/sad_test.cc
@@ -0,0 +1,951 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <limits.h>
+#include <stdio.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_codec.h"
+#include "vpx_mem/vpx_mem.h"
+#include "vpx_ports/mem.h"
+
+typedef unsigned int (*SadMxNFunc)(const uint8_t *src_ptr,
+                                   int src_stride,
+                                   const uint8_t *ref_ptr,
+                                   int ref_stride);
+typedef std::tr1::tuple<int, int, SadMxNFunc, int> SadMxNParam;
+
+typedef uint32_t (*SadMxNAvgFunc)(const uint8_t *src_ptr,
+                                  int src_stride,
+                                  const uint8_t *ref_ptr,
+                                  int ref_stride,
+                                  const uint8_t *second_pred);
+typedef std::tr1::tuple<int, int, SadMxNAvgFunc, int> SadMxNAvgParam;
+
+typedef void (*SadMxNx4Func)(const uint8_t *src_ptr,
+                             int src_stride,
+                             const uint8_t *const ref_ptr[],
+                             int ref_stride,
+                             uint32_t *sad_array);
+typedef std::tr1::tuple<int, int, SadMxNx4Func, int> SadMxNx4Param;
+
+using libvpx_test::ACMRandom;
+
+namespace {
+class SADTestBase : public ::testing::Test {
+ public:
+  SADTestBase(int width, int height, int bit_depth) :
+      width_(width), height_(height), bd_(bit_depth) {}
+
+  static void SetUpTestCase() {
+    source_data8_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBlockSize));
+    reference_data8_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize));
+    second_pred8_ = reinterpret_cast<uint8_t*>(
+        vpx_memalign(kDataAlignment, 64*64));
+    source_data16_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment, kDataBlockSize*sizeof(uint16_t)));
+    reference_data16_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment, kDataBufferSize*sizeof(uint16_t)));
+    second_pred16_ = reinterpret_cast<uint16_t*>(
+        vpx_memalign(kDataAlignment, 64*64*sizeof(uint16_t)));
+  }
+
+  static void TearDownTestCase() {
+    vpx_free(source_data8_);
+    source_data8_ = NULL;
+    vpx_free(reference_data8_);
+    reference_data8_ = NULL;
+    vpx_free(second_pred8_);
+    second_pred8_ = NULL;
+    vpx_free(source_data16_);
+    source_data16_ = NULL;
+    vpx_free(reference_data16_);
+    reference_data16_ = NULL;
+    vpx_free(second_pred16_);
+    second_pred16_ = NULL;
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  // Handle blocks up to 4 blocks 64x64 with stride up to 128
+  static const int kDataAlignment = 16;
+  static const int kDataBlockSize = 64 * 128;
+  static const int kDataBufferSize = 4 * kDataBlockSize;
+
+  virtual void SetUp() {
+    if (bd_ == -1) {
+      use_high_bit_depth_ = false;
+      bit_depth_ = VPX_BITS_8;
+      source_data_ = source_data8_;
+      reference_data_ = reference_data8_;
+      second_pred_ = second_pred8_;
+#if CONFIG_VP9_HIGHBITDEPTH
+    } else {
+      use_high_bit_depth_ = true;
+      bit_depth_ = static_cast<vpx_bit_depth_t>(bd_);
+      source_data_ = CONVERT_TO_BYTEPTR(source_data16_);
+      reference_data_ = CONVERT_TO_BYTEPTR(reference_data16_);
+      second_pred_ = CONVERT_TO_BYTEPTR(second_pred16_);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    }
+    mask_ = (1 << bit_depth_) - 1;
+    source_stride_ = (width_ + 31) & ~31;
+    reference_stride_ = width_ * 2;
+    rnd_.Reset(ACMRandom::DeterministicSeed());
+  }
+
+  virtual uint8_t *GetReference(int block_idx) {
+#if CONFIG_VP9_HIGHBITDEPTH
+    if (use_high_bit_depth_)
+      return CONVERT_TO_BYTEPTR(CONVERT_TO_SHORTPTR(reference_data_) +
+                                block_idx * kDataBlockSize);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    return reference_data_ + block_idx * kDataBlockSize;
+  }
+
+  // Sum of Absolute Differences. Given two blocks, calculate the absolute
+  // difference between two pixels in the same relative location; accumulate.
+  unsigned int ReferenceSAD(int block_idx) {
+    unsigned int sad = 0;
+      const uint8_t *const reference8 = GetReference(block_idx);
+      const uint8_t *const source8 = source_data_;
+#if CONFIG_VP9_HIGHBITDEPTH
+      const uint16_t *const reference16 =
+          CONVERT_TO_SHORTPTR(GetReference(block_idx));
+      const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < width_; ++w) {
+        if (!use_high_bit_depth_) {
+          sad += abs(source8[h * source_stride_ + w] -
+                     reference8[h * reference_stride_ + w]);
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          sad += abs(source16[h * source_stride_ + w] -
+                     reference16[h * reference_stride_ + w]);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+    }
+    return sad;
+  }
+
+  // Sum of Absolute Differences Average. Given two blocks, and a prediction
+  // calculate the absolute difference between one pixel and average of the
+  // corresponding and predicted pixels; accumulate.
+  unsigned int ReferenceSADavg(int block_idx) {
+    unsigned int sad = 0;
+    const uint8_t *const reference8 = GetReference(block_idx);
+    const uint8_t *const source8 = source_data_;
+    const uint8_t *const second_pred8 = second_pred_;
+#if CONFIG_VP9_HIGHBITDEPTH
+    const uint16_t *const reference16 =
+        CONVERT_TO_SHORTPTR(GetReference(block_idx));
+    const uint16_t *const source16 = CONVERT_TO_SHORTPTR(source_data_);
+    const uint16_t *const second_pred16 = CONVERT_TO_SHORTPTR(second_pred_);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < width_; ++w) {
+        if (!use_high_bit_depth_) {
+          const int tmp = second_pred8[h * width_ + w] +
+              reference8[h * reference_stride_ + w];
+          const uint8_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1);
+          sad += abs(source8[h * source_stride_ + w] - comp_pred);
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          const int tmp = second_pred16[h * width_ + w] +
+              reference16[h * reference_stride_ + w];
+          const uint16_t comp_pred = ROUND_POWER_OF_TWO(tmp, 1);
+          sad += abs(source16[h * source_stride_ + w] - comp_pred);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+    }
+    return sad;
+  }
+
+  void FillConstant(uint8_t *data, int stride, uint16_t fill_constant) {
+    uint8_t *data8 = data;
+#if CONFIG_VP9_HIGHBITDEPTH
+    uint16_t *data16 = CONVERT_TO_SHORTPTR(data);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < width_; ++w) {
+        if (!use_high_bit_depth_) {
+          data8[h * stride + w] = static_cast<uint8_t>(fill_constant);
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          data16[h * stride + w] = fill_constant;
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+    }
+  }
+
+  void FillRandom(uint8_t *data, int stride) {
+    uint8_t *data8 = data;
+#if CONFIG_VP9_HIGHBITDEPTH
+    uint16_t *data16 = CONVERT_TO_SHORTPTR(data);
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+    for (int h = 0; h < height_; ++h) {
+      for (int w = 0; w < width_; ++w) {
+        if (!use_high_bit_depth_) {
+          data8[h * stride + w] = rnd_.Rand8();
+#if CONFIG_VP9_HIGHBITDEPTH
+        } else {
+          data16[h * stride + w] = rnd_.Rand16() & mask_;
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+        }
+      }
+    }
+  }
+
+  int width_, height_, mask_, bd_;
+  vpx_bit_depth_t bit_depth_;
+  static uint8_t *source_data_;
+  static uint8_t *reference_data_;
+  static uint8_t *second_pred_;
+  int source_stride_;
+  bool use_high_bit_depth_;
+  static uint8_t *source_data8_;
+  static uint8_t *reference_data8_;
+  static uint8_t *second_pred8_;
+  static uint16_t *source_data16_;
+  static uint16_t *reference_data16_;
+  static uint16_t *second_pred16_;
+  int reference_stride_;
+
+  ACMRandom rnd_;
+};
+
+class SADx4Test
+    : public SADTestBase,
+      public ::testing::WithParamInterface<SadMxNx4Param> {
+ public:
+  SADx4Test() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {}
+
+ protected:
+  void SADs(unsigned int *results) {
+    const uint8_t *references[] = {GetReference(0), GetReference(1),
+                                   GetReference(2), GetReference(3)};
+
+    ASM_REGISTER_STATE_CHECK(GET_PARAM(2)(source_data_, source_stride_,
+                                          references, reference_stride_,
+                                          results));
+  }
+
+  void CheckSADs() {
+    unsigned int reference_sad, exp_sad[4];
+
+    SADs(exp_sad);
+    for (int block = 0; block < 4; ++block) {
+      reference_sad = ReferenceSAD(block);
+
+      EXPECT_EQ(reference_sad, exp_sad[block]) << "block " << block;
+    }
+  }
+};
+
+class SADTest
+    : public SADTestBase,
+      public ::testing::WithParamInterface<SadMxNParam> {
+ public:
+  SADTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {}
+
+ protected:
+  unsigned int SAD(int block_idx) {
+    unsigned int ret;
+    const uint8_t *const reference = GetReference(block_idx);
+
+    ASM_REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_,
+                                                reference, reference_stride_));
+    return ret;
+  }
+
+  void CheckSAD() {
+    const unsigned int reference_sad = ReferenceSAD(0);
+    const unsigned int exp_sad = SAD(0);
+
+    ASSERT_EQ(reference_sad, exp_sad);
+  }
+};
+
+class SADavgTest
+    : public SADTestBase,
+      public ::testing::WithParamInterface<SadMxNAvgParam> {
+ public:
+  SADavgTest() : SADTestBase(GET_PARAM(0), GET_PARAM(1), GET_PARAM(3)) {}
+
+ protected:
+  unsigned int SAD_avg(int block_idx) {
+    unsigned int ret;
+    const uint8_t *const reference = GetReference(block_idx);
+
+    ASM_REGISTER_STATE_CHECK(ret = GET_PARAM(2)(source_data_, source_stride_,
+                                                reference, reference_stride_,
+                                                second_pred_));
+    return ret;
+  }
+
+  void CheckSAD() {
+    const unsigned int reference_sad = ReferenceSADavg(0);
+    const unsigned int exp_sad = SAD_avg(0);
+
+    ASSERT_EQ(reference_sad, exp_sad);
+  }
+};
+
+uint8_t *SADTestBase::source_data_ = NULL;
+uint8_t *SADTestBase::reference_data_ = NULL;
+uint8_t *SADTestBase::second_pred_ = NULL;
+uint8_t *SADTestBase::source_data8_ = NULL;
+uint8_t *SADTestBase::reference_data8_ = NULL;
+uint8_t *SADTestBase::second_pred8_ = NULL;
+uint16_t *SADTestBase::source_data16_ = NULL;
+uint16_t *SADTestBase::reference_data16_ = NULL;
+uint16_t *SADTestBase::second_pred16_ = NULL;
+
+TEST_P(SADTest, MaxRef) {
+  FillConstant(source_data_, source_stride_, 0);
+  FillConstant(reference_data_, reference_stride_, mask_);
+  CheckSAD();
+}
+
+TEST_P(SADTest, MaxSrc) {
+  FillConstant(source_data_, source_stride_, mask_);
+  FillConstant(reference_data_, reference_stride_, 0);
+  CheckSAD();
+}
+
+TEST_P(SADTest, ShortRef) {
+  const int tmp_stride = reference_stride_;
+  reference_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  CheckSAD();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADTest, UnalignedRef) {
+  // The reference frame, but not the source frame, may be unaligned for
+  // certain types of searches.
+  const int tmp_stride = reference_stride_;
+  reference_stride_ -= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  CheckSAD();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADTest, ShortSrc) {
+  const int tmp_stride = source_stride_;
+  source_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  CheckSAD();
+  source_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, MaxRef) {
+  FillConstant(source_data_, source_stride_, 0);
+  FillConstant(reference_data_, reference_stride_, mask_);
+  FillConstant(second_pred_, width_, 0);
+  CheckSAD();
+}
+TEST_P(SADavgTest, MaxSrc) {
+  FillConstant(source_data_, source_stride_, mask_);
+  FillConstant(reference_data_, reference_stride_, 0);
+  FillConstant(second_pred_, width_, 0);
+  CheckSAD();
+}
+
+TEST_P(SADavgTest, ShortRef) {
+  const int tmp_stride = reference_stride_;
+  reference_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  FillRandom(second_pred_, width_);
+  CheckSAD();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, UnalignedRef) {
+  // The reference frame, but not the source frame, may be unaligned for
+  // certain types of searches.
+  const int tmp_stride = reference_stride_;
+  reference_stride_ -= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  FillRandom(second_pred_, width_);
+  CheckSAD();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADavgTest, ShortSrc) {
+  const int tmp_stride = source_stride_;
+  source_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(reference_data_, reference_stride_);
+  FillRandom(second_pred_, width_);
+  CheckSAD();
+  source_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, MaxRef) {
+  FillConstant(source_data_, source_stride_, 0);
+  FillConstant(GetReference(0), reference_stride_, mask_);
+  FillConstant(GetReference(1), reference_stride_, mask_);
+  FillConstant(GetReference(2), reference_stride_, mask_);
+  FillConstant(GetReference(3), reference_stride_, mask_);
+  CheckSADs();
+}
+
+TEST_P(SADx4Test, MaxSrc) {
+  FillConstant(source_data_, source_stride_, mask_);
+  FillConstant(GetReference(0), reference_stride_, 0);
+  FillConstant(GetReference(1), reference_stride_, 0);
+  FillConstant(GetReference(2), reference_stride_, 0);
+  FillConstant(GetReference(3), reference_stride_, 0);
+  CheckSADs();
+}
+
+TEST_P(SADx4Test, ShortRef) {
+  int tmp_stride = reference_stride_;
+  reference_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(GetReference(0), reference_stride_);
+  FillRandom(GetReference(1), reference_stride_);
+  FillRandom(GetReference(2), reference_stride_);
+  FillRandom(GetReference(3), reference_stride_);
+  CheckSADs();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, UnalignedRef) {
+  // The reference frame, but not the source frame, may be unaligned for
+  // certain types of searches.
+  int tmp_stride = reference_stride_;
+  reference_stride_ -= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(GetReference(0), reference_stride_);
+  FillRandom(GetReference(1), reference_stride_);
+  FillRandom(GetReference(2), reference_stride_);
+  FillRandom(GetReference(3), reference_stride_);
+  CheckSADs();
+  reference_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, ShortSrc) {
+  int tmp_stride = source_stride_;
+  source_stride_ >>= 1;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(GetReference(0), reference_stride_);
+  FillRandom(GetReference(1), reference_stride_);
+  FillRandom(GetReference(2), reference_stride_);
+  FillRandom(GetReference(3), reference_stride_);
+  CheckSADs();
+  source_stride_ = tmp_stride;
+}
+
+TEST_P(SADx4Test, SrcAlignedByWidth) {
+  uint8_t * tmp_source_data = source_data_;
+  source_data_ += width_;
+  FillRandom(source_data_, source_stride_);
+  FillRandom(GetReference(0), reference_stride_);
+  FillRandom(GetReference(1), reference_stride_);
+  FillRandom(GetReference(2), reference_stride_);
+  FillRandom(GetReference(3), reference_stride_);
+  CheckSADs();
+  source_data_ = tmp_source_data;
+}
+
+using std::tr1::make_tuple;
+
+//------------------------------------------------------------------------------
+// C functions
+const SadMxNParam c_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_c, -1),
+  make_tuple(64, 32, &vpx_sad64x32_c, -1),
+  make_tuple(32, 64, &vpx_sad32x64_c, -1),
+  make_tuple(32, 32, &vpx_sad32x32_c, -1),
+  make_tuple(32, 16, &vpx_sad32x16_c, -1),
+  make_tuple(16, 32, &vpx_sad16x32_c, -1),
+  make_tuple(16, 16, &vpx_sad16x16_c, -1),
+  make_tuple(16, 8, &vpx_sad16x8_c, -1),
+  make_tuple(8, 16, &vpx_sad8x16_c, -1),
+  make_tuple(8, 8, &vpx_sad8x8_c, -1),
+  make_tuple(8, 4, &vpx_sad8x4_c, -1),
+  make_tuple(4, 8, &vpx_sad4x8_c, -1),
+  make_tuple(4, 4, &vpx_sad4x4_c, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64_c, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_c, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_c, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_c, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_c, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_c, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_c, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_c, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_c, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_c, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_c, 8),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_c, 8),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_c, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_c, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_c, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_c, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_c, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_c, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_c, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_c, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_c, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_c, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_c, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_c, 10),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_c, 10),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_c, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_c, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_c, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_c, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_c, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_c, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_c, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_c, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_c, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_c, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_c, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_c, 12),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_c, 12),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_c, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(C, SADTest, ::testing::ValuesIn(c_tests));
+
+const SadMxNAvgParam avg_c_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_avg_c, -1),
+  make_tuple(64, 32, &vpx_sad64x32_avg_c, -1),
+  make_tuple(32, 64, &vpx_sad32x64_avg_c, -1),
+  make_tuple(32, 32, &vpx_sad32x32_avg_c, -1),
+  make_tuple(32, 16, &vpx_sad32x16_avg_c, -1),
+  make_tuple(16, 32, &vpx_sad16x32_avg_c, -1),
+  make_tuple(16, 16, &vpx_sad16x16_avg_c, -1),
+  make_tuple(16, 8, &vpx_sad16x8_avg_c, -1),
+  make_tuple(8, 16, &vpx_sad8x16_avg_c, -1),
+  make_tuple(8, 8, &vpx_sad8x8_avg_c, -1),
+  make_tuple(8, 4, &vpx_sad8x4_avg_c, -1),
+  make_tuple(4, 8, &vpx_sad4x8_avg_c, -1),
+  make_tuple(4, 4, &vpx_sad4x4_avg_c, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 8),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 8),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 10),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 10),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_c, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_c, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_c, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_c, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_c, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_c, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_c, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_c, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_c, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_c, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_c, 12),
+  make_tuple(4, 8, &vpx_highbd_sad4x8_avg_c, 12),
+  make_tuple(4, 4, &vpx_highbd_sad4x4_avg_c, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(C, SADavgTest, ::testing::ValuesIn(avg_c_tests));
+
+const SadMxNx4Param x4d_c_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64x4d_c, -1),
+  make_tuple(64, 32, &vpx_sad64x32x4d_c, -1),
+  make_tuple(32, 64, &vpx_sad32x64x4d_c, -1),
+  make_tuple(32, 32, &vpx_sad32x32x4d_c, -1),
+  make_tuple(32, 16, &vpx_sad32x16x4d_c, -1),
+  make_tuple(16, 32, &vpx_sad16x32x4d_c, -1),
+  make_tuple(16, 16, &vpx_sad16x16x4d_c, -1),
+  make_tuple(16, 8, &vpx_sad16x8x4d_c, -1),
+  make_tuple(8, 16, &vpx_sad8x16x4d_c, -1),
+  make_tuple(8, 8, &vpx_sad8x8x4d_c, -1),
+  make_tuple(8, 4, &vpx_sad8x4x4d_c, -1),
+  make_tuple(4, 8, &vpx_sad4x8x4d_c, -1),
+  make_tuple(4, 4, &vpx_sad4x4x4d_c, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 8),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 8),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 10),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 10),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_c, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_c, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_c, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_c, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_c, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_c, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_c, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_c, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_c, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_c, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_c, 12),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_c, 12),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_c, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(C, SADx4Test, ::testing::ValuesIn(x4d_c_tests));
+
+//------------------------------------------------------------------------------
+// ARM functions
+#if HAVE_MEDIA
+const SadMxNParam media_tests[] = {
+  make_tuple(16, 16, &vpx_sad16x16_media, -1),
+};
+INSTANTIATE_TEST_CASE_P(MEDIA, SADTest, ::testing::ValuesIn(media_tests));
+#endif  // HAVE_MEDIA
+
+#if HAVE_NEON
+const SadMxNParam neon_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_neon, -1),
+  make_tuple(32, 32, &vpx_sad32x32_neon, -1),
+  make_tuple(16, 16, &vpx_sad16x16_neon, -1),
+  make_tuple(16, 8, &vpx_sad16x8_neon, -1),
+  make_tuple(8, 16, &vpx_sad8x16_neon, -1),
+  make_tuple(8, 8, &vpx_sad8x8_neon, -1),
+  make_tuple(4, 4, &vpx_sad4x4_neon, -1),
+};
+INSTANTIATE_TEST_CASE_P(NEON, SADTest, ::testing::ValuesIn(neon_tests));
+
+const SadMxNx4Param x4d_neon_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64x4d_neon, -1),
+  make_tuple(32, 32, &vpx_sad32x32x4d_neon, -1),
+  make_tuple(16, 16, &vpx_sad16x16x4d_neon, -1),
+};
+INSTANTIATE_TEST_CASE_P(NEON, SADx4Test, ::testing::ValuesIn(x4d_neon_tests));
+#endif  // HAVE_NEON
+
+//------------------------------------------------------------------------------
+// x86 functions
+#if HAVE_SSE2
+#if CONFIG_USE_X86INC
+const SadMxNParam sse2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_sse2, -1),
+  make_tuple(64, 32, &vpx_sad64x32_sse2, -1),
+  make_tuple(32, 64, &vpx_sad32x64_sse2, -1),
+  make_tuple(32, 32, &vpx_sad32x32_sse2, -1),
+  make_tuple(32, 16, &vpx_sad32x16_sse2, -1),
+  make_tuple(16, 32, &vpx_sad16x32_sse2, -1),
+  make_tuple(16, 16, &vpx_sad16x16_sse2, -1),
+  make_tuple(16, 8, &vpx_sad16x8_sse2, -1),
+  make_tuple(8, 16, &vpx_sad8x16_sse2, -1),
+  make_tuple(8, 8, &vpx_sad8x8_sse2, -1),
+  make_tuple(8, 4, &vpx_sad8x4_sse2, -1),
+  make_tuple(4, 8, &vpx_sad4x8_sse2, -1),
+  make_tuple(4, 4, &vpx_sad4x4_sse2, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_sse2, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_sse2, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_sse2, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_sse2, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_sse2, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_sse2, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_sse2, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_sse2, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_sse2, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_sse2, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_sse2, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(SSE2, SADTest, ::testing::ValuesIn(sse2_tests));
+
+const SadMxNAvgParam avg_sse2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_avg_sse2, -1),
+  make_tuple(64, 32, &vpx_sad64x32_avg_sse2, -1),
+  make_tuple(32, 64, &vpx_sad32x64_avg_sse2, -1),
+  make_tuple(32, 32, &vpx_sad32x32_avg_sse2, -1),
+  make_tuple(32, 16, &vpx_sad32x16_avg_sse2, -1),
+  make_tuple(16, 32, &vpx_sad16x32_avg_sse2, -1),
+  make_tuple(16, 16, &vpx_sad16x16_avg_sse2, -1),
+  make_tuple(16, 8, &vpx_sad16x8_avg_sse2, -1),
+  make_tuple(8, 16, &vpx_sad8x16_avg_sse2, -1),
+  make_tuple(8, 8, &vpx_sad8x8_avg_sse2, -1),
+  make_tuple(8, 4, &vpx_sad8x4_avg_sse2, -1),
+  make_tuple(4, 8, &vpx_sad4x8_avg_sse2, -1),
+  make_tuple(4, 4, &vpx_sad4x4_avg_sse2, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64_avg_sse2, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32_avg_sse2, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64_avg_sse2, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32_avg_sse2, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16_avg_sse2, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32_avg_sse2, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16_avg_sse2, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8_avg_sse2, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16_avg_sse2, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8_avg_sse2, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4_avg_sse2, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(SSE2, SADavgTest, ::testing::ValuesIn(avg_sse2_tests));
+
+const SadMxNx4Param x4d_sse2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64x4d_sse2, -1),
+  make_tuple(64, 32, &vpx_sad64x32x4d_sse2, -1),
+  make_tuple(32, 64, &vpx_sad32x64x4d_sse2, -1),
+  make_tuple(32, 32, &vpx_sad32x32x4d_sse2, -1),
+  make_tuple(32, 16, &vpx_sad32x16x4d_sse2, -1),
+  make_tuple(16, 32, &vpx_sad16x32x4d_sse2, -1),
+  make_tuple(16, 16, &vpx_sad16x16x4d_sse2, -1),
+  make_tuple(16, 8, &vpx_sad16x8x4d_sse2, -1),
+  make_tuple(8, 16, &vpx_sad8x16x4d_sse2, -1),
+  make_tuple(8, 8, &vpx_sad8x8x4d_sse2, -1),
+  make_tuple(8, 4, &vpx_sad8x4x4d_sse2, -1),
+  make_tuple(4, 8, &vpx_sad4x8x4d_sse2, -1),
+  make_tuple(4, 4, &vpx_sad4x4x4d_sse2, -1),
+#if CONFIG_VP9_HIGHBITDEPTH
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 8),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 8),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 8),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 8),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 8),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 8),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 8),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 8),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 8),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 8),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 8),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 8),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 8),
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 10),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 10),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 10),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 10),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 10),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 10),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 10),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 10),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 10),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 10),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 10),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 10),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 10),
+  make_tuple(64, 64, &vpx_highbd_sad64x64x4d_sse2, 12),
+  make_tuple(64, 32, &vpx_highbd_sad64x32x4d_sse2, 12),
+  make_tuple(32, 64, &vpx_highbd_sad32x64x4d_sse2, 12),
+  make_tuple(32, 32, &vpx_highbd_sad32x32x4d_sse2, 12),
+  make_tuple(32, 16, &vpx_highbd_sad32x16x4d_sse2, 12),
+  make_tuple(16, 32, &vpx_highbd_sad16x32x4d_sse2, 12),
+  make_tuple(16, 16, &vpx_highbd_sad16x16x4d_sse2, 12),
+  make_tuple(16, 8, &vpx_highbd_sad16x8x4d_sse2, 12),
+  make_tuple(8, 16, &vpx_highbd_sad8x16x4d_sse2, 12),
+  make_tuple(8, 8, &vpx_highbd_sad8x8x4d_sse2, 12),
+  make_tuple(8, 4, &vpx_highbd_sad8x4x4d_sse2, 12),
+  make_tuple(4, 8, &vpx_highbd_sad4x8x4d_sse2, 12),
+  make_tuple(4, 4, &vpx_highbd_sad4x4x4d_sse2, 12),
+#endif  // CONFIG_VP9_HIGHBITDEPTH
+};
+INSTANTIATE_TEST_CASE_P(SSE2, SADx4Test, ::testing::ValuesIn(x4d_sse2_tests));
+#endif  // CONFIG_USE_X86INC
+#endif  // HAVE_SSE2
+
+#if HAVE_SSE3
+// Only functions are x3, which do not have tests.
+#endif  // HAVE_SSE3
+
+#if HAVE_SSSE3
+// Only functions are x3, which do not have tests.
+#endif  // HAVE_SSSE3
+
+#if HAVE_SSE4_1
+// Only functions are x8, which do not have tests.
+#endif  // HAVE_SSE4_1
+
+#if HAVE_AVX2
+const SadMxNParam avx2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_avx2, -1),
+  make_tuple(64, 32, &vpx_sad64x32_avx2, -1),
+  make_tuple(32, 64, &vpx_sad32x64_avx2, -1),
+  make_tuple(32, 32, &vpx_sad32x32_avx2, -1),
+  make_tuple(32, 16, &vpx_sad32x16_avx2, -1),
+};
+INSTANTIATE_TEST_CASE_P(AVX2, SADTest, ::testing::ValuesIn(avx2_tests));
+
+const SadMxNAvgParam avg_avx2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_avg_avx2, -1),
+  make_tuple(64, 32, &vpx_sad64x32_avg_avx2, -1),
+  make_tuple(32, 64, &vpx_sad32x64_avg_avx2, -1),
+  make_tuple(32, 32, &vpx_sad32x32_avg_avx2, -1),
+  make_tuple(32, 16, &vpx_sad32x16_avg_avx2, -1),
+};
+INSTANTIATE_TEST_CASE_P(AVX2, SADavgTest, ::testing::ValuesIn(avg_avx2_tests));
+
+const SadMxNx4Param x4d_avx2_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64x4d_avx2, -1),
+  make_tuple(32, 32, &vpx_sad32x32x4d_avx2, -1),
+};
+INSTANTIATE_TEST_CASE_P(AVX2, SADx4Test, ::testing::ValuesIn(x4d_avx2_tests));
+#endif  // HAVE_AVX2
+
+//------------------------------------------------------------------------------
+// MIPS functions
+#if HAVE_MSA
+const SadMxNParam msa_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_msa, -1),
+  make_tuple(64, 32, &vpx_sad64x32_msa, -1),
+  make_tuple(32, 64, &vpx_sad32x64_msa, -1),
+  make_tuple(32, 32, &vpx_sad32x32_msa, -1),
+  make_tuple(32, 16, &vpx_sad32x16_msa, -1),
+  make_tuple(16, 32, &vpx_sad16x32_msa, -1),
+  make_tuple(16, 16, &vpx_sad16x16_msa, -1),
+  make_tuple(16, 8, &vpx_sad16x8_msa, -1),
+  make_tuple(8, 16, &vpx_sad8x16_msa, -1),
+  make_tuple(8, 8, &vpx_sad8x8_msa, -1),
+  make_tuple(8, 4, &vpx_sad8x4_msa, -1),
+  make_tuple(4, 8, &vpx_sad4x8_msa, -1),
+  make_tuple(4, 4, &vpx_sad4x4_msa, -1),
+};
+INSTANTIATE_TEST_CASE_P(MSA, SADTest, ::testing::ValuesIn(msa_tests));
+
+const SadMxNAvgParam avg_msa_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64_avg_msa, -1),
+  make_tuple(64, 32, &vpx_sad64x32_avg_msa, -1),
+  make_tuple(32, 64, &vpx_sad32x64_avg_msa, -1),
+  make_tuple(32, 32, &vpx_sad32x32_avg_msa, -1),
+  make_tuple(32, 16, &vpx_sad32x16_avg_msa, -1),
+  make_tuple(16, 32, &vpx_sad16x32_avg_msa, -1),
+  make_tuple(16, 16, &vpx_sad16x16_avg_msa, -1),
+  make_tuple(16, 8, &vpx_sad16x8_avg_msa, -1),
+  make_tuple(8, 16, &vpx_sad8x16_avg_msa, -1),
+  make_tuple(8, 8, &vpx_sad8x8_avg_msa, -1),
+  make_tuple(8, 4, &vpx_sad8x4_avg_msa, -1),
+  make_tuple(4, 8, &vpx_sad4x8_avg_msa, -1),
+  make_tuple(4, 4, &vpx_sad4x4_avg_msa, -1),
+};
+INSTANTIATE_TEST_CASE_P(MSA, SADavgTest, ::testing::ValuesIn(avg_msa_tests));
+
+const SadMxNx4Param x4d_msa_tests[] = {
+  make_tuple(64, 64, &vpx_sad64x64x4d_msa, -1),
+  make_tuple(64, 32, &vpx_sad64x32x4d_msa, -1),
+  make_tuple(32, 64, &vpx_sad32x64x4d_msa, -1),
+  make_tuple(32, 32, &vpx_sad32x32x4d_msa, -1),
+  make_tuple(32, 16, &vpx_sad32x16x4d_msa, -1),
+  make_tuple(16, 32, &vpx_sad16x32x4d_msa, -1),
+  make_tuple(16, 16, &vpx_sad16x16x4d_msa, -1),
+  make_tuple(16, 8, &vpx_sad16x8x4d_msa, -1),
+  make_tuple(8, 16, &vpx_sad8x16x4d_msa, -1),
+  make_tuple(8, 8, &vpx_sad8x8x4d_msa, -1),
+  make_tuple(8, 4, &vpx_sad8x4x4d_msa, -1),
+  make_tuple(4, 8, &vpx_sad4x8x4d_msa, -1),
+  make_tuple(4, 4, &vpx_sad4x4x4d_msa, -1),
+};
+INSTANTIATE_TEST_CASE_P(MSA, SADx4Test, ::testing::ValuesIn(x4d_msa_tests));
+#endif  // HAVE_MSA
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/set_maps.sh b/src/third_party/libvpx/test/set_maps.sh
new file mode 100755
index 0000000..e7c8d43
--- /dev/null
+++ b/src/third_party/libvpx/test/set_maps.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx set_maps example. To add new tests to this file,
+##  do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to set_maps_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required, and set_maps must exist in
+# $LIBVPX_BIN_PATH.
+set_maps_verify_environment() {
+  if [ ! -e "${YUV_RAW_INPUT}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+  if [ -z "$(vpx_tool_path set_maps)" ]; then
+    elog "set_maps not found. It must exist in LIBVPX_BIN_PATH or its parent."
+    return 1
+  fi
+}
+
+# Runs set_maps using the codec specified by $1.
+set_maps() {
+  local encoder="$(vpx_tool_path set_maps)"
+  local codec="$1"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/set_maps_${codec}.ivf"
+
+  eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+      "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" \
+      ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+}
+
+set_maps_vp8() {
+  if [ "$(vp8_encode_available)" = "yes" ]; then
+    set_maps vp8 || return 1
+  fi
+}
+
+set_maps_vp9() {
+  if [ "$(vp9_encode_available)" = "yes" ]; then
+    set_maps vp9 || return 1
+  fi
+}
+
+set_maps_tests="set_maps_vp8
+                set_maps_vp9"
+
+run_tests set_maps_verify_environment "${set_maps_tests}"
diff --git a/src/third_party/libvpx/test/set_roi.cc b/src/third_party/libvpx/test/set_roi.cc
new file mode 100644
index 0000000..fea8cca
--- /dev/null
+++ b/src/third_party/libvpx/test/set_roi.cc
@@ -0,0 +1,184 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <math.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/acm_random.h"
+#include "vp8/encoder/onyx_int.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+using libvpx_test::ACMRandom;
+
+namespace {
+
+TEST(VP8RoiMapTest, ParameterCheck) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  int delta_q[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
+  int delta_lf[MAX_MB_SEGMENTS] = { -2, -25, 0, 31 };
+  unsigned int threshold[MAX_MB_SEGMENTS] = { 0, 100, 200, 300 };
+
+  const int internalq_trans[] = {
+    0,   1,  2,  3,  4,  5,  7,  8,
+    9,  10, 12, 13, 15, 17, 18, 19,
+    20,  21, 23, 24, 25, 26, 27, 28,
+    29,  30, 31, 33, 35, 37, 39, 41,
+    43,  45, 47, 49, 51, 53, 55, 57,
+    59,  61, 64, 67, 70, 73, 76, 79,
+    82,  85, 88, 91, 94, 97, 100, 103,
+    106, 109, 112, 115, 118, 121, 124, 127,
+  };
+
+  // Initialize elements of cpi with valid defaults.
+  VP8_COMP cpi;
+  cpi.mb.e_mbd.mb_segement_abs_delta = SEGMENT_DELTADATA;
+  cpi.cyclic_refresh_mode_enabled = 0;
+  cpi.mb.e_mbd.segmentation_enabled = 0;
+  cpi.mb.e_mbd.update_mb_segmentation_map = 0;
+  cpi.mb.e_mbd.update_mb_segmentation_data = 0;
+  cpi.common.mb_rows = 240 >> 4;
+  cpi.common.mb_cols = 320 >> 4;
+  const int mbs = (cpi.common.mb_rows * cpi.common.mb_cols);
+  memset(cpi.segment_feature_data, 0, sizeof(cpi.segment_feature_data));
+
+  // Segment map
+  cpi.segmentation_map = reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
+
+  // Allocate memory for the source memory map.
+  unsigned char *roi_map =
+    reinterpret_cast<unsigned char *>(vpx_calloc(mbs, 1));
+  memset(&roi_map[mbs >> 2], 1, (mbs >> 2));
+  memset(&roi_map[mbs >> 1], 2, (mbs >> 2));
+  memset(&roi_map[mbs -(mbs >> 2)], 3, (mbs >> 2));
+
+  // Do a test call with valid parameters.
+  int roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+                                  cpi.common.mb_cols, delta_q, delta_lf,
+                                  threshold);
+  EXPECT_EQ(0, roi_retval)
+        << "vp8_set_roimap roi failed with default test parameters";
+
+  // Check that the values in the cpi structure get set as expected.
+  if (roi_retval == 0) {
+    // Check that the segment map got set.
+    const int mapcompare = memcmp(roi_map, cpi.segmentation_map, mbs);
+    EXPECT_EQ(0, mapcompare) << "segment map error";
+
+    // Check the q deltas (note the need to translate into
+    // the interanl range of 0-127.
+    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+      const int transq = internalq_trans[abs(delta_q[i])];
+      if (abs(cpi.segment_feature_data[MB_LVL_ALT_Q][i]) != transq) {
+          EXPECT_EQ(transq, cpi.segment_feature_data[MB_LVL_ALT_Q][i])
+                    << "segment delta_q  error";
+          break;
+      }
+    }
+
+    // Check the loop filter deltas
+    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+      if (cpi.segment_feature_data[MB_LVL_ALT_LF][i] != delta_lf[i]) {
+        EXPECT_EQ(delta_lf[i], cpi.segment_feature_data[MB_LVL_ALT_LF][i])
+                  << "segment delta_lf error";
+        break;
+      }
+    }
+
+    // Check the breakout thresholds
+    for (int i = 0; i < MAX_MB_SEGMENTS; ++i) {
+      unsigned int breakout =
+        static_cast<unsigned int>(cpi.segment_encode_breakout[i]);
+
+      if (threshold[i] != breakout) {
+        EXPECT_EQ(threshold[i], breakout)
+                  << "breakout threshold error";
+        break;
+      }
+    }
+
+    // Segmentation, and segmentation update flages should be set.
+    EXPECT_EQ(1, cpi.mb.e_mbd.segmentation_enabled)
+              << "segmentation_enabled error";
+    EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_map)
+              << "update_mb_segmentation_map error";
+    EXPECT_EQ(1, cpi.mb.e_mbd.update_mb_segmentation_data)
+              << "update_mb_segmentation_data error";
+
+
+    // Try a range of delta q and lf parameters (some legal, some not)
+    for (int i = 0; i < 1000; ++i) {
+      int rand_deltas[4];
+      int deltas_valid;
+      rand_deltas[0] = rnd(160) - 80;
+      rand_deltas[1] = rnd(160) - 80;
+      rand_deltas[2] = rnd(160) - 80;
+      rand_deltas[3] = rnd(160) - 80;
+
+      deltas_valid = ((abs(rand_deltas[0]) <= 63) &&
+                      (abs(rand_deltas[1]) <= 63) &&
+                      (abs(rand_deltas[2]) <= 63) &&
+                      (abs(rand_deltas[3]) <= 63)) ? 0 : -1;
+
+      // Test with random delta q values.
+      roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+                                  cpi.common.mb_cols, rand_deltas,
+                                  delta_lf, threshold);
+      EXPECT_EQ(deltas_valid, roi_retval) << "dq range check error";
+
+      // One delta_q error shown at a time
+      if (deltas_valid != roi_retval)
+        break;
+
+      // Test with random loop filter values.
+      roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+                                  cpi.common.mb_cols, delta_q,
+                                  rand_deltas, threshold);
+      EXPECT_EQ(deltas_valid, roi_retval) << "dlf range check error";
+
+      // One delta loop filter error shown at a time
+      if (deltas_valid != roi_retval)
+        break;
+    }
+
+    // Test that we report and error if cyclic refresh is enabled.
+    cpi.cyclic_refresh_mode_enabled = 1;
+    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+                                cpi.common.mb_cols, delta_q,
+                                delta_lf, threshold);
+    EXPECT_EQ(-1, roi_retval) << "cyclic refresh check error";
+    cpi.cyclic_refresh_mode_enabled = 0;
+
+    // Test invalid number of rows or colums.
+    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows + 1,
+                                cpi.common.mb_cols, delta_q,
+                                delta_lf, threshold);
+    EXPECT_EQ(-1, roi_retval) << "MB rows bounds check error";
+
+    roi_retval = vp8_set_roimap(&cpi, roi_map, cpi.common.mb_rows,
+                                cpi.common.mb_cols - 1, delta_q,
+                                delta_lf, threshold);
+    EXPECT_EQ(-1, roi_retval) << "MB cols bounds check error";
+  }
+
+  // Free allocated memory
+  if (cpi.segmentation_map)
+    vpx_free(cpi.segmentation_map);
+  if (roi_map)
+    vpx_free(roi_map);
+};
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/simple_decoder.sh b/src/third_party/libvpx/test/simple_decoder.sh
new file mode 100755
index 0000000..7eeaf71
--- /dev/null
+++ b/src/third_party/libvpx/test/simple_decoder.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx simple_decoder example code. To add new tests to
+##  this file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to simple_decoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: Make sure input is available:
+#   $VP8_IVF_FILE and $VP9_IVF_FILE are required.
+simple_decoder_verify_environment() {
+  if [ ! -e "${VP8_IVF_FILE}" ] || [ ! -e "${VP9_IVF_FILE}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Runs simple_decoder using $1 as input file. $2 is the codec name, and is used
+# solely to name the output file.
+simple_decoder() {
+  local decoder="${LIBVPX_BIN_PATH}/simple_decoder${VPX_TEST_EXE_SUFFIX}"
+  local input_file="$1"
+  local codec="$2"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/simple_decoder_${codec}.raw"
+
+  if [ ! -x "${decoder}" ]; then
+    elog "${decoder} does not exist or is not executable."
+    return 1
+  fi
+
+  eval "${VPX_TEST_PREFIX}" "${decoder}" "${input_file}" "${output_file}" \
+      ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+}
+
+simple_decoder_vp8() {
+  if [ "$(vp8_decode_available)" = "yes" ]; then
+    simple_decoder "${VP8_IVF_FILE}" vp8 || return 1
+  fi
+}
+
+simple_decoder_vp9() {
+  if [ "$(vp9_decode_available)" = "yes" ]; then
+    simple_decoder "${VP9_IVF_FILE}" vp9 || return 1
+  fi
+}
+
+simple_decoder_tests="simple_decoder_vp8
+                      simple_decoder_vp9"
+
+run_tests simple_decoder_verify_environment "${simple_decoder_tests}"
diff --git a/src/third_party/libvpx/test/simple_encoder.sh b/src/third_party/libvpx/test/simple_encoder.sh
new file mode 100755
index 0000000..ee633ae
--- /dev/null
+++ b/src/third_party/libvpx/test/simple_encoder.sh
@@ -0,0 +1,59 @@
+#!/bin/sh
+##
+##  Copyright (c) 2014 The WebM 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.
+##
+##  This file tests the libvpx simple_encoder example. To add new tests to this
+##  file, do the following:
+##    1. Write a shell function (this is your test).
+##    2. Add the function to simple_encoder_tests (on a new line).
+##
+. $(dirname $0)/tools_common.sh
+
+# Environment check: $YUV_RAW_INPUT is required.
+simple_encoder_verify_environment() {
+  if [ ! -e "${YUV_RAW_INPUT}" ]; then
+    echo "Libvpx test data must exist in LIBVPX_TEST_DATA_PATH."
+    return 1
+  fi
+}
+
+# Runs simple_encoder using the codec specified by $1 with a frame limit of 100.
+simple_encoder() {
+  local encoder="${LIBVPX_BIN_PATH}/simple_encoder${VPX_TEST_EXE_SUFFIX}"
+  local codec="$1"
+  local output_file="${VPX_TEST_OUTPUT_DIR}/simple_encoder_${codec}.ivf"
+
+  if [ ! -x "${encoder}" ]; then
+    elog "${encoder} does not exist or is not executable."
+    return 1
+  fi
+
+  eval "${VPX_TEST_PREFIX}" "${encoder}" "${codec}" "${YUV_RAW_INPUT_WIDTH}" \
+      "${YUV_RAW_INPUT_HEIGHT}" "${YUV_RAW_INPUT}" "${output_file}" 9999 0 100 \
+      ${devnull}
+
+  [ -e "${output_file}" ] || return 1
+}
+
+simple_encoder_vp8() {
+  if [ "$(vp8_encode_available)" = "yes" ]; then
+    simple_encoder vp8 || return 1
+  fi
+}
+
+simple_encoder_vp9() {
+  if [ "$(vp9_encode_available)" = "yes" ]; then
+    simple_encoder vp9 || return 1
+  fi
+}
+
+simple_encoder_tests="simple_encoder_vp8
+                      simple_encoder_vp9"
+
+run_tests simple_encoder_verify_environment "${simple_encoder_tests}"
diff --git a/src/third_party/libvpx/test/sixtap_predict_test.cc b/src/third_party/libvpx/test/sixtap_predict_test.cc
new file mode 100644
index 0000000..304a148
--- /dev/null
+++ b/src/third_party/libvpx/test/sixtap_predict_test.cc
@@ -0,0 +1,233 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#include "./vp8_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/register_state_check.h"
+#include "test/util.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+typedef void (*SixtapPredictFunc)(uint8_t *src_ptr,
+                                  int src_pixels_per_line,
+                                  int xoffset,
+                                  int yoffset,
+                                  uint8_t *dst_ptr,
+                                  int dst_pitch);
+
+typedef std::tr1::tuple<int, int, SixtapPredictFunc> SixtapPredictParam;
+
+class SixtapPredictTest
+    : public ::testing::TestWithParam<SixtapPredictParam> {
+ public:
+  static void SetUpTestCase() {
+    src_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kSrcSize));
+    dst_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize));
+    dst_c_ = reinterpret_cast<uint8_t*>(vpx_memalign(kDataAlignment, kDstSize));
+  }
+
+  static void TearDownTestCase() {
+    vpx_free(src_);
+    src_ = NULL;
+    vpx_free(dst_);
+    dst_ = NULL;
+    vpx_free(dst_c_);
+    dst_c_ = NULL;
+  }
+
+  virtual void TearDown() {
+    libvpx_test::ClearSystemState();
+  }
+
+ protected:
+  // Make test arrays big enough for 16x16 functions. Six-tap filters
+  // need 5 extra pixels outside of the macroblock.
+  static const int kSrcStride = 21;
+  static const int kDstStride = 16;
+  static const int kDataAlignment = 16;
+  static const int kSrcSize = kSrcStride * kSrcStride + 1;
+  static const int kDstSize = kDstStride * kDstStride;
+
+  virtual void SetUp() {
+    width_ = GET_PARAM(0);
+    height_ = GET_PARAM(1);
+    sixtap_predict_ = GET_PARAM(2);
+    memset(src_, 0, kSrcSize);
+    memset(dst_, 0, kDstSize);
+    memset(dst_c_, 0, kDstSize);
+  }
+
+  int width_;
+  int height_;
+  SixtapPredictFunc sixtap_predict_;
+  // The src stores the macroblock we will filter on, and makes it 1 byte larger
+  // in order to test unaligned access. The result is stored in dst and dst_c(c
+  // reference code result).
+  static uint8_t* src_;
+  static uint8_t* dst_;
+  static uint8_t* dst_c_;
+};
+
+uint8_t* SixtapPredictTest::src_ = NULL;
+uint8_t* SixtapPredictTest::dst_ = NULL;
+uint8_t* SixtapPredictTest::dst_c_ = NULL;
+
+TEST_P(SixtapPredictTest, TestWithPresetData) {
+  // Test input
+  static const uint8_t test_data[kSrcSize] = {
+    216, 184, 4, 191, 82, 92, 41, 0, 1, 226, 236, 172, 20, 182, 42, 226, 177,
+    79, 94, 77, 179, 203, 206, 198, 22, 192, 19, 75, 17, 192, 44, 233, 120,
+    48, 168, 203, 141, 210, 203, 143, 180, 184, 59, 201, 110, 102, 171, 32,
+    182, 10, 109, 105, 213, 60, 47, 236, 253, 67, 55, 14, 3, 99, 247, 124,
+    148, 159, 71, 34, 114, 19, 177, 38, 203, 237, 239, 58, 83, 155, 91, 10,
+    166, 201, 115, 124, 5, 163, 104, 2, 231, 160, 16, 234, 4, 8, 103, 153,
+    167, 174, 187, 26, 193, 109, 64, 141, 90, 48, 200, 174, 204, 36, 184,
+    114, 237, 43, 238, 242, 207, 86, 245, 182, 247, 6, 161, 251, 14, 8, 148,
+    182, 182, 79, 208, 120, 188, 17, 6, 23, 65, 206, 197, 13, 242, 126, 128,
+    224, 170, 110, 211, 121, 197, 200, 47, 188, 207, 208, 184, 221, 216, 76,
+    148, 143, 156, 100, 8, 89, 117, 14, 112, 183, 221, 54, 197, 208, 180, 69,
+    176, 94, 180, 131, 215, 121, 76, 7, 54, 28, 216, 238, 249, 176, 58, 142,
+    64, 215, 242, 72, 49, 104, 87, 161, 32, 52, 216, 230, 4, 141, 44, 181,
+    235, 224, 57, 195, 89, 134, 203, 144, 162, 163, 126, 156, 84, 185, 42,
+    148, 145, 29, 221, 194, 134, 52, 100, 166, 105, 60, 140, 110, 201, 184,
+    35, 181, 153, 93, 121, 243, 227, 68, 131, 134, 232, 2, 35, 60, 187, 77,
+    209, 76, 106, 174, 15, 241, 227, 115, 151, 77, 175, 36, 187, 121, 221,
+    223, 47, 118, 61, 168, 105, 32, 237, 236, 167, 213, 238, 202, 17, 170,
+    24, 226, 247, 131, 145, 6, 116, 117, 121, 11, 194, 41, 48, 126, 162, 13,
+    93, 209, 131, 154, 122, 237, 187, 103, 217, 99, 60, 200, 45, 78, 115, 69,
+    49, 106, 200, 194, 112, 60, 56, 234, 72, 251, 19, 120, 121, 182, 134, 215,
+    135, 10, 114, 2, 247, 46, 105, 209, 145, 165, 153, 191, 243, 12, 5, 36,
+    119, 206, 231, 231, 11, 32, 209, 83, 27, 229, 204, 149, 155, 83, 109, 35,
+    93, 223, 37, 84, 14, 142, 37, 160, 52, 191, 96, 40, 204, 101, 77, 67, 52,
+    53, 43, 63, 85, 253, 147, 113, 226, 96, 6, 125, 179, 115, 161, 17, 83,
+    198, 101, 98, 85, 139, 3, 137, 75, 99, 178, 23, 201, 255, 91, 253, 52,
+    134, 60, 138, 131, 208, 251, 101, 48, 2, 227, 228, 118, 132, 245, 202,
+    75, 91, 44, 160, 231, 47, 41, 50, 147, 220, 74, 92, 219, 165, 89, 16
+  };
+
+  // Expected result
+  static const uint8_t expected_dst[kDstSize] = {
+    117, 102, 74, 135, 42, 98, 175, 206, 70, 73, 222, 197, 50, 24, 39, 49, 38,
+    105, 90, 47, 169, 40, 171, 215, 200, 73, 109, 141, 53, 85, 177, 164, 79,
+    208, 124, 89, 212, 18, 81, 145, 151, 164, 217, 153, 91, 154, 102, 102,
+    159, 75, 164, 152, 136, 51, 213, 219, 186, 116, 193, 224, 186, 36, 231,
+    208, 84, 211, 155, 167, 35, 59, 42, 76, 216, 149, 73, 201, 78, 149, 184,
+    100, 96, 196, 189, 198, 188, 235, 195, 117, 129, 120, 129, 49, 25, 133,
+    113, 69, 221, 114, 70, 143, 99, 157, 108, 189, 140, 78, 6, 55, 65, 240,
+    255, 245, 184, 72, 90, 100, 116, 131, 39, 60, 234, 167, 33, 160, 88, 185,
+    200, 157, 159, 176, 127, 151, 138, 102, 168, 106, 170, 86, 82, 219, 189,
+    76, 33, 115, 197, 106, 96, 198, 136, 97, 141, 237, 151, 98, 137, 191,
+    185, 2, 57, 95, 142, 91, 255, 185, 97, 137, 76, 162, 94, 173, 131, 193,
+    161, 81, 106, 72, 135, 222, 234, 137, 66, 137, 106, 243, 210, 147, 95,
+    15, 137, 110, 85, 66, 16, 96, 167, 147, 150, 173, 203, 140, 118, 196,
+    84, 147, 160, 19, 95, 101, 123, 74, 132, 202, 82, 166, 12, 131, 166,
+    189, 170, 159, 85, 79, 66, 57, 152, 132, 203, 194, 0, 1, 56, 146, 180,
+    224, 156, 28, 83, 181, 79, 76, 80, 46, 160, 175, 59, 106, 43, 87, 75,
+    136, 85, 189, 46, 71, 200, 90
+  };
+
+  uint8_t *src = const_cast<uint8_t*>(test_data);
+
+  ASM_REGISTER_STATE_CHECK(
+      sixtap_predict_(&src[kSrcStride * 2 + 2 + 1], kSrcStride,
+                      2, 2, dst_, kDstStride));
+
+  for (int i = 0; i < height_; ++i)
+    for (int j = 0; j < width_; ++j)
+      ASSERT_EQ(expected_dst[i * kDstStride + j], dst_[i * kDstStride + j])
+          << "i==" << (i * width_ + j);
+}
+
+using libvpx_test::ACMRandom;
+
+TEST_P(SixtapPredictTest, TestWithRandomData) {
+  ACMRandom rnd(ACMRandom::DeterministicSeed());
+  for (int i = 0; i < kSrcSize; ++i)
+    src_[i] = rnd.Rand8();
+
+  // Run tests for all possible offsets.
+  for (int xoffset = 0; xoffset < 8; ++xoffset) {
+    for (int yoffset = 0; yoffset < 8; ++yoffset) {
+      // Call c reference function.
+      // Move start point to next pixel to test if the function reads
+      // unaligned data correctly.
+      vp8_sixtap_predict16x16_c(&src_[kSrcStride * 2 + 2 + 1], kSrcStride,
+                                xoffset, yoffset, dst_c_, kDstStride);
+
+      // Run test.
+      ASM_REGISTER_STATE_CHECK(
+          sixtap_predict_(&src_[kSrcStride * 2 + 2 + 1], kSrcStride,
+                          xoffset, yoffset, dst_, kDstStride));
+
+      for (int i = 0; i < height_; ++i)
+        for (int j = 0; j < width_; ++j)
+          ASSERT_EQ(dst_c_[i * kDstStride + j], dst_[i * kDstStride + j])
+              << "i==" << (i * width_ + j);
+    }
+  }
+}
+
+using std::tr1::make_tuple;
+
+INSTANTIATE_TEST_CASE_P(
+    C, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_c),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_c),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_c),
+        make_tuple(4, 4, &vp8_sixtap_predict4x4_c)));
+#if HAVE_NEON
+INSTANTIATE_TEST_CASE_P(
+    NEON, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_neon),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_neon),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_neon)));
+#endif
+#if HAVE_MMX
+INSTANTIATE_TEST_CASE_P(
+    MMX, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_mmx),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_mmx),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_mmx),
+        make_tuple(4, 4, &vp8_sixtap_predict4x4_mmx)));
+#endif
+#if HAVE_SSE2
+INSTANTIATE_TEST_CASE_P(
+    SSE2, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_sse2),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_sse2),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_sse2)));
+#endif
+#if HAVE_SSSE3
+INSTANTIATE_TEST_CASE_P(
+    SSSE3, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_ssse3),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_ssse3),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_ssse3),
+        make_tuple(4, 4, &vp8_sixtap_predict4x4_ssse3)));
+#endif
+#if HAVE_MSA
+INSTANTIATE_TEST_CASE_P(
+    MSA, SixtapPredictTest, ::testing::Values(
+        make_tuple(16, 16, &vp8_sixtap_predict16x16_msa),
+        make_tuple(8, 8, &vp8_sixtap_predict8x8_msa),
+        make_tuple(8, 4, &vp8_sixtap_predict8x4_msa),
+        make_tuple(4, 4, &vp8_sixtap_predict4x4_msa)));
+#endif
+}  // namespace
diff --git a/src/third_party/libvpx/test/superframe_test.cc b/src/third_party/libvpx/test/superframe_test.cc
new file mode 100644
index 0000000..90aa75b
--- /dev/null
+++ b/src/third_party/libvpx/test/superframe_test.cc
@@ -0,0 +1,113 @@
+/*
+ *  Copyright (c) 2012 The WebM 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 <climits>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/encode_test_driver.h"
+#include "test/i420_video_source.h"
+#include "test/util.h"
+
+namespace {
+
+const int kTestMode = 0;
+const int kSuperframeSyntax = 1;
+
+typedef std::tr1::tuple<libvpx_test::TestMode,int> SuperframeTestParam;
+
+class SuperframeTest : public ::libvpx_test::EncoderTest,
+    public ::libvpx_test::CodecTestWithParam<SuperframeTestParam> {
+ protected:
+  SuperframeTest() : EncoderTest(GET_PARAM(0)), modified_buf_(NULL),
+      last_sf_pts_(0) {}
+  virtual ~SuperframeTest() {}
+
+  virtual void SetUp() {
+    InitializeConfig();
+    const SuperframeTestParam input = GET_PARAM(1);
+    const libvpx_test::TestMode mode = std::tr1::get<kTestMode>(input);
+    const int syntax = std::tr1::get<kSuperframeSyntax>(input);
+    SetMode(mode);
+    sf_count_ = 0;
+    sf_count_max_ = INT_MAX;
+    is_vp10_style_superframe_ = syntax;
+  }
+
+  virtual void TearDown() {
+    delete[] modified_buf_;
+  }
+
+  virtual void PreEncodeFrameHook(libvpx_test::VideoSource *video,
+                                  libvpx_test::Encoder *encoder) {
+    if (video->frame() == 1) {
+      encoder->Control(VP8E_SET_ENABLEAUTOALTREF, 1);
+    }
+  }
+
+  virtual const vpx_codec_cx_pkt_t * MutateEncoderOutputHook(
+      const vpx_codec_cx_pkt_t *pkt) {
+    if (pkt->kind != VPX_CODEC_CX_FRAME_PKT)
+      return pkt;
+
+    const uint8_t *buffer = reinterpret_cast<uint8_t*>(pkt->data.frame.buf);
+    const uint8_t marker = buffer[pkt->data.frame.sz - 1];
+    const int frames = (marker & 0x7) + 1;
+    const int mag = ((marker >> 3) & 3) + 1;
+    const unsigned int index_sz =
+        2 + mag * (frames - is_vp10_style_superframe_);
+    if ((marker & 0xe0) == 0xc0 &&
+        pkt->data.frame.sz >= index_sz &&
+        buffer[pkt->data.frame.sz - index_sz] == marker) {
+      // frame is a superframe. strip off the index.
+      if (modified_buf_)
+        delete[] modified_buf_;
+      modified_buf_ = new uint8_t[pkt->data.frame.sz - index_sz];
+      memcpy(modified_buf_, pkt->data.frame.buf,
+             pkt->data.frame.sz - index_sz);
+      modified_pkt_ = *pkt;
+      modified_pkt_.data.frame.buf = modified_buf_;
+      modified_pkt_.data.frame.sz -= index_sz;
+
+      sf_count_++;
+      last_sf_pts_ = pkt->data.frame.pts;
+      return &modified_pkt_;
+    }
+
+    // Make sure we do a few frames after the last SF
+    abort_ |= sf_count_ > sf_count_max_ &&
+              pkt->data.frame.pts - last_sf_pts_ >= 5;
+    return pkt;
+  }
+
+  int is_vp10_style_superframe_;
+  int sf_count_;
+  int sf_count_max_;
+  vpx_codec_cx_pkt_t modified_pkt_;
+  uint8_t *modified_buf_;
+  vpx_codec_pts_t last_sf_pts_;
+};
+
+TEST_P(SuperframeTest, TestSuperframeIndexIsOptional) {
+  sf_count_max_ = 0;  // early exit on successful test.
+  cfg_.g_lag_in_frames = 25;
+
+  ::libvpx_test::I420VideoSource video("hantro_collage_w352h288.yuv", 352, 288,
+                                       30, 1, 0, 40);
+  ASSERT_NO_FATAL_FAILURE(RunLoop(&video));
+  EXPECT_EQ(sf_count_, 1);
+}
+
+VP9_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine(
+    ::testing::Values(::libvpx_test::kTwoPassGood),
+    ::testing::Values(0)));
+
+VP10_INSTANTIATE_TEST_CASE(SuperframeTest, ::testing::Combine(
+    ::testing::Values(::libvpx_test::kTwoPassGood),
+    ::testing::Values(CONFIG_MISC_FIXES)));
+}  // namespace
diff --git a/src/third_party/libvpx/test/svc_test.cc b/src/third_party/libvpx/test/svc_test.cc
new file mode 100644
index 0000000..b955cee
--- /dev/null
+++ b/src/third_party/libvpx/test/svc_test.cc
@@ -0,0 +1,797 @@
+/*
+ *  Copyright (c) 2013 The WebM 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>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/i420_video_source.h"
+
+#include "vp9/decoder/vp9_decoder.h"
+
+#include "vpx/svc_context.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vpx_encoder.h"
+
+namespace {
+
+using libvpx_test::CodecFactory;
+using libvpx_test::Decoder;
+using libvpx_test::DxDataIterator;
+using libvpx_test::VP9CodecFactory;
+
+class SvcTest : public ::testing::Test {
+ protected:
+  static const uint32_t kWidth = 352;
+  static const uint32_t kHeight = 288;
+
+  SvcTest()
+      : codec_iface_(0),
+        test_file_name_("hantro_collage_w352h288.yuv"),
+        codec_initialized_(false),
+        decoder_(0) {
+    memset(&svc_, 0, sizeof(svc_));
+    memset(&codec_, 0, sizeof(codec_));
+    memset(&codec_enc_, 0, sizeof(codec_enc_));
+  }
+
+  virtual ~SvcTest() {}
+
+  virtual void SetUp() {
+    svc_.log_level = SVC_LOG_DEBUG;
+    svc_.log_print = 0;
+
+    codec_iface_ = vpx_codec_vp9_cx();
+    const vpx_codec_err_t res =
+        vpx_codec_enc_config_default(codec_iface_, &codec_enc_, 0);
+    EXPECT_EQ(VPX_CODEC_OK, res);
+
+    codec_enc_.g_w = kWidth;
+    codec_enc_.g_h = kHeight;
+    codec_enc_.g_timebase.num = 1;
+    codec_enc_.g_timebase.den = 60;
+    codec_enc_.kf_min_dist = 100;
+    codec_enc_.kf_max_dist = 100;
+
+    vpx_codec_dec_cfg_t dec_cfg = vpx_codec_dec_cfg_t();
+    VP9CodecFactory codec_factory;
+    decoder_ = codec_factory.CreateDecoder(dec_cfg, 0);
+
+    tile_columns_ = 0;
+    tile_rows_ = 0;
+  }
+
+  virtual void TearDown() {
+    ReleaseEncoder();
+    delete(decoder_);
+  }
+
+  void InitializeEncoder() {
+    const vpx_codec_err_t res =
+        vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+    EXPECT_EQ(VPX_CODEC_OK, res);
+    vpx_codec_control(&codec_, VP8E_SET_CPUUSED, 4);  // Make the test faster
+    vpx_codec_control(&codec_, VP9E_SET_TILE_COLUMNS, tile_columns_);
+    vpx_codec_control(&codec_, VP9E_SET_TILE_ROWS, tile_rows_);
+    codec_initialized_ = true;
+  }
+
+  void ReleaseEncoder() {
+    vpx_svc_release(&svc_);
+    if (codec_initialized_) vpx_codec_destroy(&codec_);
+    codec_initialized_ = false;
+  }
+
+  void GetStatsData(std::string *const stats_buf) {
+    vpx_codec_iter_t iter = NULL;
+    const vpx_codec_cx_pkt_t *cx_pkt;
+
+    while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
+      if (cx_pkt->kind == VPX_CODEC_STATS_PKT) {
+        EXPECT_GT(cx_pkt->data.twopass_stats.sz, 0U);
+        ASSERT_TRUE(cx_pkt->data.twopass_stats.buf != NULL);
+        stats_buf->append(static_cast<char*>(cx_pkt->data.twopass_stats.buf),
+                          cx_pkt->data.twopass_stats.sz);
+      }
+    }
+  }
+
+  void Pass1EncodeNFrames(const int n, const int layers,
+                          std::string *const stats_buf) {
+    vpx_codec_err_t res;
+
+    ASSERT_GT(n, 0);
+    ASSERT_GT(layers, 0);
+    svc_.spatial_layers = layers;
+    codec_enc_.g_pass = VPX_RC_FIRST_PASS;
+    InitializeEncoder();
+
+    libvpx_test::I420VideoSource video(test_file_name_,
+                                       codec_enc_.g_w, codec_enc_.g_h,
+                                       codec_enc_.g_timebase.den,
+                                       codec_enc_.g_timebase.num, 0, 30);
+    video.Begin();
+
+    for (int i = 0; i < n; ++i) {
+      res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
+                           video.duration(), VPX_DL_GOOD_QUALITY);
+      ASSERT_EQ(VPX_CODEC_OK, res);
+      GetStatsData(stats_buf);
+      video.Next();
+    }
+
+    // Flush encoder and test EOS packet.
+    res = vpx_svc_encode(&svc_, &codec_, NULL, video.pts(),
+                         video.duration(), VPX_DL_GOOD_QUALITY);
+    ASSERT_EQ(VPX_CODEC_OK, res);
+    GetStatsData(stats_buf);
+
+    ReleaseEncoder();
+  }
+
+  void StoreFrames(const size_t max_frame_received,
+                   struct vpx_fixed_buf *const outputs,
+                   size_t *const frame_received) {
+    vpx_codec_iter_t iter = NULL;
+    const vpx_codec_cx_pkt_t *cx_pkt;
+
+    while ((cx_pkt = vpx_codec_get_cx_data(&codec_, &iter)) != NULL) {
+      if (cx_pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+        const size_t frame_size = cx_pkt->data.frame.sz;
+
+        EXPECT_GT(frame_size, 0U);
+        ASSERT_TRUE(cx_pkt->data.frame.buf != NULL);
+        ASSERT_LT(*frame_received, max_frame_received);
+
+        if (*frame_received == 0)
+          EXPECT_EQ(1, !!(cx_pkt->data.frame.flags & VPX_FRAME_IS_KEY));
+
+        outputs[*frame_received].buf = malloc(frame_size + 16);
+        ASSERT_TRUE(outputs[*frame_received].buf != NULL);
+        memcpy(outputs[*frame_received].buf, cx_pkt->data.frame.buf,
+               frame_size);
+        outputs[*frame_received].sz = frame_size;
+        ++(*frame_received);
+      }
+    }
+  }
+
+  void Pass2EncodeNFrames(std::string *const stats_buf,
+                          const int n, const int layers,
+                          struct vpx_fixed_buf *const outputs) {
+    vpx_codec_err_t res;
+    size_t frame_received = 0;
+
+    ASSERT_TRUE(outputs != NULL);
+    ASSERT_GT(n, 0);
+    ASSERT_GT(layers, 0);
+    svc_.spatial_layers = layers;
+    codec_enc_.rc_target_bitrate = 500;
+    if (codec_enc_.g_pass == VPX_RC_LAST_PASS) {
+      ASSERT_TRUE(stats_buf != NULL);
+      ASSERT_GT(stats_buf->size(), 0U);
+      codec_enc_.rc_twopass_stats_in.buf = &(*stats_buf)[0];
+      codec_enc_.rc_twopass_stats_in.sz = stats_buf->size();
+    }
+    InitializeEncoder();
+
+    libvpx_test::I420VideoSource video(test_file_name_,
+                                       codec_enc_.g_w, codec_enc_.g_h,
+                                       codec_enc_.g_timebase.den,
+                                       codec_enc_.g_timebase.num, 0, 30);
+    video.Begin();
+
+    for (int i = 0; i < n; ++i) {
+      res = vpx_svc_encode(&svc_, &codec_, video.img(), video.pts(),
+                           video.duration(), VPX_DL_GOOD_QUALITY);
+      ASSERT_EQ(VPX_CODEC_OK, res);
+      StoreFrames(n, outputs, &frame_received);
+      video.Next();
+    }
+
+    // Flush encoder.
+    res = vpx_svc_encode(&svc_, &codec_, NULL, 0,
+                         video.duration(), VPX_DL_GOOD_QUALITY);
+    EXPECT_EQ(VPX_CODEC_OK, res);
+    StoreFrames(n, outputs, &frame_received);
+
+    EXPECT_EQ(frame_received, static_cast<size_t>(n));
+
+    ReleaseEncoder();
+  }
+
+  void DecodeNFrames(const struct vpx_fixed_buf *const inputs, const int n) {
+    int decoded_frames = 0;
+    int received_frames = 0;
+
+    ASSERT_TRUE(inputs != NULL);
+    ASSERT_GT(n, 0);
+
+    for (int i = 0; i < n; ++i) {
+      ASSERT_TRUE(inputs[i].buf != NULL);
+      ASSERT_GT(inputs[i].sz, 0U);
+      const vpx_codec_err_t res_dec =
+          decoder_->DecodeFrame(static_cast<const uint8_t *>(inputs[i].buf),
+                                inputs[i].sz);
+      ASSERT_EQ(VPX_CODEC_OK, res_dec) << decoder_->DecodeError();
+      ++decoded_frames;
+
+      DxDataIterator dec_iter = decoder_->GetDxData();
+      while (dec_iter.Next() != NULL) {
+        ++received_frames;
+      }
+    }
+    EXPECT_EQ(decoded_frames, n);
+    EXPECT_EQ(received_frames, n);
+  }
+
+  void DropEnhancementLayers(struct vpx_fixed_buf *const inputs,
+                             const int num_super_frames,
+                             const int remained_spatial_layers) {
+    ASSERT_TRUE(inputs != NULL);
+    ASSERT_GT(num_super_frames, 0);
+    ASSERT_GT(remained_spatial_layers, 0);
+
+    for (int i = 0; i < num_super_frames; ++i) {
+      uint32_t frame_sizes[8] = {0};
+      int frame_count = 0;
+      int frames_found = 0;
+      int frame;
+      ASSERT_TRUE(inputs[i].buf != NULL);
+      ASSERT_GT(inputs[i].sz, 0U);
+
+      vpx_codec_err_t res =
+          vp9_parse_superframe_index(static_cast<const uint8_t*>(inputs[i].buf),
+                                     inputs[i].sz, frame_sizes, &frame_count,
+                                     NULL, NULL);
+      ASSERT_EQ(VPX_CODEC_OK, res);
+
+      if (frame_count == 0) {
+        // There's no super frame but only a single frame.
+        ASSERT_EQ(1, remained_spatial_layers);
+      } else {
+        // Found a super frame.
+        uint8_t *frame_data = static_cast<uint8_t*>(inputs[i].buf);
+        uint8_t *frame_start = frame_data;
+        for (frame = 0; frame < frame_count; ++frame) {
+          // Looking for a visible frame.
+          if (frame_data[0] & 0x02) {
+            ++frames_found;
+            if (frames_found == remained_spatial_layers)
+              break;
+          }
+          frame_data += frame_sizes[frame];
+        }
+        ASSERT_LT(frame, frame_count) << "Couldn't find a visible frame. "
+            << "remained_spatial_layers: " << remained_spatial_layers
+            << "    super_frame: " << i;
+        if (frame == frame_count - 1)
+          continue;
+
+        frame_data += frame_sizes[frame];
+
+        // We need to add one more frame for multiple frame contexts.
+        uint8_t marker =
+            static_cast<const uint8_t*>(inputs[i].buf)[inputs[i].sz - 1];
+        const uint32_t mag = ((marker >> 3) & 0x3) + 1;
+        const size_t index_sz = 2 + mag * frame_count;
+        const size_t new_index_sz = 2 + mag * (frame + 1);
+        marker &= 0x0f8;
+        marker |= frame;
+
+        // Copy existing frame sizes.
+        memmove(frame_data + 1, frame_start + inputs[i].sz - index_sz + 1,
+                new_index_sz - 2);
+        // New marker.
+        frame_data[0] = marker;
+        frame_data += (mag * (frame + 1) + 1);
+
+        *frame_data++ = marker;
+        inputs[i].sz = frame_data - frame_start;
+      }
+    }
+  }
+
+  void FreeBitstreamBuffers(struct vpx_fixed_buf *const inputs, const int n) {
+    ASSERT_TRUE(inputs != NULL);
+    ASSERT_GT(n, 0);
+
+    for (int i = 0; i < n; ++i) {
+      free(inputs[i].buf);
+      inputs[i].buf = NULL;
+      inputs[i].sz = 0;
+    }
+  }
+
+  SvcContext svc_;
+  vpx_codec_ctx_t codec_;
+  struct vpx_codec_enc_cfg codec_enc_;
+  vpx_codec_iface_t *codec_iface_;
+  std::string test_file_name_;
+  bool codec_initialized_;
+  Decoder *decoder_;
+  int tile_columns_;
+  int tile_rows_;
+};
+
+TEST_F(SvcTest, SvcInit) {
+  // test missing parameters
+  vpx_codec_err_t res = vpx_svc_init(NULL, &codec_, codec_iface_, &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+  res = vpx_svc_init(&svc_, NULL, codec_iface_, &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+  res = vpx_svc_init(&svc_, &codec_, NULL, &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_init(&svc_, &codec_, codec_iface_, NULL);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  svc_.spatial_layers = 6;  // too many layers
+  res = vpx_svc_init(&svc_, &codec_, codec_iface_, &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  svc_.spatial_layers = 0;  // use default layers
+  InitializeEncoder();
+  EXPECT_EQ(VPX_SS_DEFAULT_LAYERS, svc_.spatial_layers);
+}
+
+TEST_F(SvcTest, InitTwoLayers) {
+  svc_.spatial_layers = 2;
+  InitializeEncoder();
+}
+
+TEST_F(SvcTest, InvalidOptions) {
+  vpx_codec_err_t res = vpx_svc_set_options(&svc_, NULL);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "not-an-option=1");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+}
+
+TEST_F(SvcTest, SetLayersOption) {
+  vpx_codec_err_t res = vpx_svc_set_options(&svc_, "spatial-layers=3");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  InitializeEncoder();
+  EXPECT_EQ(3, svc_.spatial_layers);
+}
+
+TEST_F(SvcTest, SetMultipleOptions) {
+  vpx_codec_err_t res =
+      vpx_svc_set_options(&svc_, "spatial-layers=2 scale-factors=1/3,2/3");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  InitializeEncoder();
+  EXPECT_EQ(2, svc_.spatial_layers);
+}
+
+TEST_F(SvcTest, SetScaleFactorsOption) {
+  svc_.spatial_layers = 2;
+  vpx_codec_err_t res =
+      vpx_svc_set_options(&svc_, "scale-factors=not-scale-factors");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "scale-factors=1/3, 3*3");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "scale-factors=1/3");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "scale-factors=1/3,2/3");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  InitializeEncoder();
+}
+
+TEST_F(SvcTest, SetQuantizersOption) {
+  svc_.spatial_layers = 2;
+  vpx_codec_err_t res = vpx_svc_set_options(&svc_, "max-quantizers=nothing");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "min-quantizers=nothing");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "max-quantizers=40");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "min-quantizers=40");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "max-quantizers=30,30 min-quantizers=40,40");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "max-quantizers=40,40 min-quantizers=30,30");
+  InitializeEncoder();
+}
+
+TEST_F(SvcTest, SetAutoAltRefOption) {
+  svc_.spatial_layers = 5;
+  vpx_codec_err_t res = vpx_svc_set_options(&svc_, "auto-alt-refs=none");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  res = vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1,1,0");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
+  InitializeEncoder();
+}
+
+// Test that decoder can handle an SVC frame as the first frame in a sequence.
+TEST_F(SvcTest, OnePassEncodeOneFrame) {
+  codec_enc_.g_pass = VPX_RC_ONE_PASS;
+  vpx_fixed_buf output = {0};
+  Pass2EncodeNFrames(NULL, 1, 2, &output);
+  DecodeNFrames(&output, 1);
+  FreeBitstreamBuffers(&output, 1);
+}
+
+TEST_F(SvcTest, OnePassEncodeThreeFrames) {
+  codec_enc_.g_pass = VPX_RC_ONE_PASS;
+  codec_enc_.g_lag_in_frames = 0;
+  vpx_fixed_buf outputs[3];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(NULL, 3, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 3);
+  FreeBitstreamBuffers(&outputs[0], 3);
+}
+
+TEST_F(SvcTest, TwoPassEncode10Frames) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(10, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode20FramesWithAltRef) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(20, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
+  vpx_fixed_buf outputs[20];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 20);
+  FreeBitstreamBuffers(&outputs[0], 20);
+}
+
+TEST_F(SvcTest, TwoPassEncode2SpatialLayersDecodeBaseLayerOnly) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(10, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+  DropEnhancementLayers(&outputs[0], 10, 1);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode5SpatialLayersDecode54321Layers) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(10, 5, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=0,1,1,1,0");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 5, &outputs[0]);
+
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 4);
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 3);
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 2);
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 1);
+  DecodeNFrames(&outputs[0], 10);
+
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2SNRLayers) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
+  Pass1EncodeNFrames(20, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_svc_set_options(&svc_,
+                      "auto-alt-refs=1,1 scale-factors=1/1,1/1");
+  vpx_fixed_buf outputs[20];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 20, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 20);
+  FreeBitstreamBuffers(&outputs[0], 20);
+}
+
+TEST_F(SvcTest, TwoPassEncode3SNRLayersDecode321Layers) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
+  Pass1EncodeNFrames(20, 3, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  vpx_svc_set_options(&svc_,
+                      "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1");
+  vpx_fixed_buf outputs[20];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 20, 3, &outputs[0]);
+  DecodeNFrames(&outputs[0], 20);
+  DropEnhancementLayers(&outputs[0], 20, 2);
+  DecodeNFrames(&outputs[0], 20);
+  DropEnhancementLayers(&outputs[0], 20, 1);
+  DecodeNFrames(&outputs[0], 20);
+
+  FreeBitstreamBuffers(&outputs[0], 20);
+}
+
+TEST_F(SvcTest, SetMultipleFrameContextsOption) {
+  svc_.spatial_layers = 5;
+  vpx_codec_err_t res =
+      vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
+  EXPECT_EQ(VPX_CODEC_OK, res);
+  res = vpx_svc_init(&svc_, &codec_, vpx_codec_vp9_cx(), &codec_enc_);
+  EXPECT_EQ(VPX_CODEC_INVALID_PARAM, res);
+
+  svc_.spatial_layers = 2;
+  res = vpx_svc_set_options(&svc_, "multi-frame-contexts=1");
+  InitializeEncoder();
+}
+
+TEST_F(SvcTest, TwoPassEncode2SpatialLayersWithMultipleFrameContexts) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(10, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest,
+       TwoPassEncode2SpatialLayersWithMultipleFrameContextsDecodeBaselayer) {
+  // First pass encode
+  std::string stats_buf;
+  Pass1EncodeNFrames(10, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+  DropEnhancementLayers(&outputs[0], 10, 1);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2SNRLayersWithMultipleFrameContexts) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1");
+  Pass1EncodeNFrames(10, 2, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1 scale-factors=1/1,1/1 "
+                      "multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 2, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest,
+       TwoPassEncode3SNRLayersWithMultipleFrameContextsDecode321Layer) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1,1/1,1/1");
+  Pass1EncodeNFrames(10, 3, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1,1,1 scale-factors=1/1,1/1,1/1 "
+                      "multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 3, &outputs[0]);
+
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 2);
+  DecodeNFrames(&outputs[0], 10);
+  DropEnhancementLayers(&outputs[0], 10, 1);
+  DecodeNFrames(&outputs[0], 10);
+
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2TemporalLayers) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithMultipleFrameContexts) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
+                      "multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2TemporalLayersDecodeBaseLayer) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+
+  vpx_fixed_buf base_layer[5];
+  for (int i = 0; i < 5; ++i)
+    base_layer[i] = outputs[i * 2];
+
+  DecodeNFrames(&base_layer[0], 5);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest,
+       TwoPassEncode2TemporalLayersWithMultipleFrameContextsDecodeBaseLayer) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  codec_enc_.g_error_resilient = 0;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
+                      "multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+
+  vpx_fixed_buf base_layer[5];
+  for (int i = 0; i < 5; ++i)
+    base_layer[i] = outputs[i * 2];
+
+  DecodeNFrames(&base_layer[0], 5);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest, TwoPassEncode2TemporalLayersWithTiles) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1");
+  codec_enc_.g_w = 704;
+  codec_enc_.g_h = 144;
+  tile_columns_ = 1;
+  tile_rows_ = 1;
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+TEST_F(SvcTest,
+       TwoPassEncode2TemporalLayersWithMultipleFrameContextsAndTiles) {
+  // First pass encode
+  std::string stats_buf;
+  vpx_svc_set_options(&svc_, "scale-factors=1/1");
+  svc_.temporal_layers = 2;
+  Pass1EncodeNFrames(10, 1, &stats_buf);
+
+  // Second pass encode
+  codec_enc_.g_pass = VPX_RC_LAST_PASS;
+  svc_.temporal_layers = 2;
+  codec_enc_.g_error_resilient = 0;
+  codec_enc_.g_w = 704;
+  codec_enc_.g_h = 144;
+  tile_columns_ = 1;
+  tile_rows_ = 1;
+  vpx_svc_set_options(&svc_, "auto-alt-refs=1 scale-factors=1/1 "
+                      "multi-frame-contexts=1");
+  vpx_fixed_buf outputs[10];
+  memset(&outputs[0], 0, sizeof(outputs));
+  Pass2EncodeNFrames(&stats_buf, 10, 1, &outputs[0]);
+  DecodeNFrames(&outputs[0], 10);
+  FreeBitstreamBuffers(&outputs[0], 10);
+}
+
+}  // namespace
diff --git a/src/third_party/libvpx/test/test-data.mk b/src/third_party/libvpx/test/test-data.mk
new file mode 100644
index 0000000..05a0885
--- /dev/null
+++ b/src/third_party/libvpx/test/test-data.mk
@@ -0,0 +1,863 @@
+LIBVPX_TEST_SRCS-yes += test-data.mk
+
+# Encoder test source
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_collage_w352h288.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += hantro_odd.yuv
+
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_420.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_422.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_10_440.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_420.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_422.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_12_440.yuv
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420_a10-1.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_420.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_422.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_ENCODERS) += park_joy_90p_8_440.yuv
+
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_credits.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += rush_hour_444.y4m
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += screendata.y4m
+
+# Test vectors
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-001.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-002.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-003.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-004.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-005.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-006.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-007.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-008.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-009.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-010.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-011.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-012.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-013.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-014.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-015.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-016.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-017.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-00-comprehensive-018.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1400.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1411.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1416.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-01-intra-1417.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1402.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1412.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1418.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-02-inter-1424.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-01.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-02.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-03.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-04.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1401.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1403.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1407.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1408.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1409.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1410.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1413.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1414.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1415.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1425.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1426.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1427.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1432.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1435.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1436.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1437.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1441.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-03-segmentation-1442.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1404.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1405.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-04-partitions-1406.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1428.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1429.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1430.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1431.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1433.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1434.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1438.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1439.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1440.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-05-sharpness-1443.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP8_DECODER) += vp80-06-smallsize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-00.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-02.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-03.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-04.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-05.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-06.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-07.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-09.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-11.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-12.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-13.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-14.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-15.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-17.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-19.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-20.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-21.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-22.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-23.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-24.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-25.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-26.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-27.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-28.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-29.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-30.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-31.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-33.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-35.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-36.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-37.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-38.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-39.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-40.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-41.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-42.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-43.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-44.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-45.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-46.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-47.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-48.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-49.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-50.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-51.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-52.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-53.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-54.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-55.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-56.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-57.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-58.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-59.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-60.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-61.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-62.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-00-quantizer-63.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-3.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-5.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-6.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-01-sharpness-7.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-08x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-10x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-16x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-18x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-32x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-34x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-64x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x08.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x10.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x18.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x32.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x34.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x64.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-66x66.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-130x132.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x130.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-132x132.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-178x180.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x178.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-180x180.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-02-size-lf-1920x1080.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-deltaq.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-196x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-198x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-200x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-202x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-208x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-210x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-224x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x196.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x198.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x200.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x202.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x208.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x210.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x224.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-226x226.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-03-size-352x288.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-05-resize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-06-bilinear.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-07-frame_parallel-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile-4x4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x2_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x4_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-08-tile_1x8_frame_parallel.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-aq2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-lf_deltas.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-09-subpixel-00.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-10-show-existing-frame2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x287.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-351x288.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-11-size-352x287.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_1.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_2.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-12-droppable_3.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-13-largescaling.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-1-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-16-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-2-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-16.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-fp-tiles-8-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-15-segkey_adpq.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-16-intra-only.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-17-show-existing-frame.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-18-resize.ivf.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-19-skip-02.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp91-2-04-yuv444.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-01.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-20-big_superframe-02.webm.md5
+ifeq ($(CONFIG_VP9_HIGHBITDEPTH),yes)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-10bit-yuv420.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp92-2-20-12bit-yuv420.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv422.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv440.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-10bit-yuv444.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp93-2-20-12bit-yuv444.webm.md5
+endif  # CONFIG_VP9_HIGHBITDEPTH
+
+# Invalid files for testing libvpx error checking.
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-01-v3.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-02-v2.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-03-v3.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp91-2-mixedrefcsp-444to420.ivf.res
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-1.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += invalid-vp90-2-07-frame_parallel-3.webm
+
+ifeq ($(CONFIG_DECODE_PERF_TESTS),yes)
+# Encode / Decode test
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
+# BBB VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_426x240_tile_1x1_180kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_640x360_tile_1x2_337kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_854x480_tile_1x2_651kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm
+# Sintel VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_426x182_tile_1x1_171kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_640x272_tile_1x2_318kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_854x364_tile_1x2_621kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm
+# TOS VP9 streams
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_426x178_tile_1x1_181kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_640x266_tile_1x2_336kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_656kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_1306kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm
+endif  # CONFIG_DECODE_PERF_TESTS
+
+ifeq ($(CONFIG_ENCODE_PERF_TESTS),yes)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += desktop_640_360_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += kirland_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcomoving_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += macmarcostationary_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_1280_720_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += niklas_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomanarrows_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += tacomasmallcameramovement_640_480_30.yuv
+LIBVPX_TEST_DATA-$(CONFIG_VP9_ENCODER) += thaloundeskmtg_640_480_30.yuv
+endif  # CONFIG_ENCODE_PERF_TESTS
+
+# sort and remove duplicates
+LIBVPX_TEST_DATA-yes := $(sort $(LIBVPX_TEST_DATA-yes))
+
+# VP9 dynamic resizing test (decoder)
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x180_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_320x240_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x360_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_640x480_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm
+LIBVPX_TEST_DATA-$(CONFIG_VP9_DECODER) += vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5
diff --git a/src/third_party/libvpx/test/test-data.sha1 b/src/third_party/libvpx/test/test-data.sha1
new file mode 100644
index 0000000..a4ed174
--- /dev/null
+++ b/src/third_party/libvpx/test/test-data.sha1
@@ -0,0 +1,836 @@
+d5dfb0151c9051f8c85999255645d7a23916d3c0 *hantro_collage_w352h288.yuv
+b87815bf86020c592ccc7a846ba2e28ec8043902 *hantro_odd.yuv
+76024eb753cdac6a5e5703aaea189d35c3c30ac7 *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf
+7448d8798a4380162d4b56f9b452e2f6f9e24e7a *invalid-vp90-2-00-quantizer-00.webm.ivf.s5861_r01-05_b6-.v2.ivf.res
+83f50908c8dc0ef8760595447a2ff7727489542e *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-.ivf.res
+c123d1f9f02fb4143abb5e271916e3a3080de8f6 *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf
+456d1493e52d32a5c30edf44a27debc1fa6b253a *invalid-vp90-2-00-quantizer-11.webm.ivf.s52984_r01-05_b6-z.ivf.res
+fe346136b9b8c1e6f6084cc106485706915795e4 *invalid-vp90-01-v3.webm
+5d9474c0309b7ca09a182d888f73b37a8fe1362c *invalid-vp90-01-v3.webm.res
+d78e2fceba5ac942246503ec8366f879c4775ca5 *invalid-vp90-02-v2.webm
+8e2eff4af87d2b561cce2365713269e301457ef3 *invalid-vp90-02-v2.webm.res
+df1a1453feb3c00d7d89746c7003b4163523bff3 *invalid-vp90-03-v3.webm
+4935c62becc68c13642a03db1e6d3e2331c1c612 *invalid-vp90-03-v3.webm.res
+d637297561dd904eb2c97a9015deeb31c4a1e8d2 *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm
+3a204bdbeaa3c6458b77bcebb8366d107267f55d *invalid-vp90-2-08-tile_1x4_frame_parallel_all_key.webm.res
+a432f96ff0a787268e2f94a8092ab161a18d1b06 *park_joy_90p_10_420.y4m
+0b194cc312c3a2e84d156a221b0a5eb615dfddc5 *park_joy_90p_10_422.y4m
+ff0e0a21dc2adc95b8c1b37902713700655ced17 *park_joy_90p_10_444.y4m
+c934da6fb8cc54ee2a8c17c54cf6076dac37ead0 *park_joy_90p_10_440.yuv
+614c32ae1eca391e867c70d19974f0d62664dd99 *park_joy_90p_12_420.y4m
+c92825f1ea25c5c37855083a69faac6ac4641a9e *park_joy_90p_12_422.y4m
+b592189b885b6cc85db55cc98512a197d73d3b34 *park_joy_90p_12_444.y4m
+82c1bfcca368c2f22bad7d693d690d5499ecdd11 *park_joy_90p_12_440.yuv
+b9e1e90aece2be6e2c90d89e6ab2372d5f8c792d *park_joy_90p_8_420_a10-1.y4m
+4e0eb61e76f0684188d9bc9f3ce61f6b6b77bb2c *park_joy_90p_8_420.y4m
+7a193ff7dfeb96ba5f82b2afd7afa9e1fe83d947 *park_joy_90p_8_422.y4m
+bdb7856e6bc93599bdda05c2e773a9f22b6c6d03 *park_joy_90p_8_444.y4m
+81e1f3843748438b8f2e71db484eb22daf72e939 *park_joy_90p_8_440.yuv
+b1f1c3ec79114b9a0651af24ce634afb44a9a419 *rush_hour_444.y4m
+5184c46ddca8b1fadd16742e8500115bc8f749da *vp80-00-comprehensive-001.ivf
+65bf1bbbced81b97bd030f376d1b7f61a224793f *vp80-00-comprehensive-002.ivf
+906b4c1e99eb734504c504b3f1ad8052137ce672 *vp80-00-comprehensive-003.ivf
+ec144b1af53af895db78355785650b96dd3f0ade *vp80-00-comprehensive-004.ivf
+afc7091785c62f1c121c4554a2830c30704587d9 *vp80-00-comprehensive-005.ivf
+42ea9d55c818145d06a9b633b8e85c6a6164fd3e *vp80-00-comprehensive-006.ivf
+e5b3a73ab79fe024c14309d653d6bed92902ee3b *vp80-00-comprehensive-007.ivf
+f3c50a58875930adfb84525c0ef59d7e4c08540c *vp80-00-comprehensive-008.ivf
+4b2841fdb83db51ae322096ae468bbb9dc2c8362 *vp80-00-comprehensive-009.ivf
+efbff736e3a91ab6a98c5bc2dce65d645944c7b1 *vp80-00-comprehensive-010.ivf
+6b315102cae008d22a3d2c231be92cb704a222f8 *vp80-00-comprehensive-011.ivf
+f3214a4fea14c2d5ec689936c1613f274c859ee8 *vp80-00-comprehensive-012.ivf
+e4094e96d308c8a35b74c480a43d853c5294cd34 *vp80-00-comprehensive-013.ivf
+5b0adfaf60a69e0aaf3ec021a39d0a68fc0e1b5a *vp80-00-comprehensive-014.ivf
+e8467688ddf26b5000664f904faf0d70506aa653 *vp80-00-comprehensive-015.ivf
+aab55582337dfd2a39ff54fb2576a91910d49337 *vp80-00-comprehensive-016.ivf
+1ba24724f80203c9bae4f1d0f99d534721980016 *vp80-00-comprehensive-017.ivf
+143a15512b46f436280ddb4d0e6411eb4af434f2 *vp80-00-comprehensive-018.ivf
+c5baeaf5714fdfb3a8bc960a8e33ac438e83b16b *vp80-01-intra-1400.ivf
+f383955229afe3408453e316d11553d923ca60d5 *vp80-01-intra-1411.ivf
+84e1f4343f174c9f3c83f834bac3196fb325bf2c *vp80-01-intra-1416.ivf
+fb6e712a47dd57a28a3727d2ae2c97a8b7c7ca51 *vp80-01-intra-1417.ivf
+71ea772d3e9d315b8cbecf41207b8a237c34853b *vp80-02-inter-1402.ivf
+d85dbc4271525dcd128c503f936fe69091d1f8d0 *vp80-02-inter-1412.ivf
+d4e5d3ad56511867d025f93724d090f92ba6ec3d *vp80-02-inter-1418.ivf
+91791cbcc37c60f35dbd8090bacb54e5ec6dd4fa *vp80-02-inter-1424.ivf
+17fbfe2fea70f6e2f3fa6ca4efaae6c0b03b5f02 *vp80-03-segmentation-01.ivf
+3c3600dbbcde08e20d54c66fe3b7eadd4f09bdbb *vp80-03-segmentation-02.ivf
+c156778d5340967d4b369c490848076e92f1f875 *vp80-03-segmentation-03.ivf
+d25dcff6c60e87a1af70945b8911b6b4998533b0 *vp80-03-segmentation-04.ivf
+362baba2ce454c9db21218f35e81c27a5ed0b730 *vp80-03-segmentation-1401.ivf
+d223ae7ee748ce07e74c4679bfd219e84aa9f4b0 *vp80-03-segmentation-1403.ivf
+033adf7f3a13836a3f1cffcb87c1972900f2b5c6 *vp80-03-segmentation-1407.ivf
+4d51dfbf9f3e2c590ec99d1d6f59dd731d04375f *vp80-03-segmentation-1408.ivf
+f37a62b197c2600d75e0ccfbb31b60efdedac251 *vp80-03-segmentation-1409.ivf
+eb25bd7bfba5b2f6935018a930f42d123b1e7fcd *vp80-03-segmentation-1410.ivf
+b9d5c436663a30c27cfff84b53a002e501258843 *vp80-03-segmentation-1413.ivf
+6da92b9d1a180cc3a8afe348ab12258f5a37be1a *vp80-03-segmentation-1414.ivf
+a4f5842602886bd669f115f93d8a35c035cb0948 *vp80-03-segmentation-1415.ivf
+f295dceb8ef278b77251b3f9df8aee22e161d547 *vp80-03-segmentation-1425.ivf
+198dbf9f36f733200e432664cc8c5752d59779de *vp80-03-segmentation-1426.ivf
+7704804e32f5de976803929934a7fafe101ac7b0 *vp80-03-segmentation-1427.ivf
+831ccd862ea95ca025d2f3bd8b88678752f5416d *vp80-03-segmentation-1432.ivf
+b3c11978529289f9109f2766fcaba3ebc40e11ef *vp80-03-segmentation-1435.ivf
+a835a731f5520ebfc1002c40121264d0020559ac *vp80-03-segmentation-1436.ivf
+1d1732942f773bb2a5775fcb9689b1579ce28eab *vp80-03-segmentation-1437.ivf
+db04799adfe089dfdf74dbd43cc05ede7161f99e *vp80-03-segmentation-1441.ivf
+7caf39b3f20cfd52b998210878062e52a5edf1e6 *vp80-03-segmentation-1442.ivf
+3607f6bb4ee106c38fa1ea370dc4ff8b8cde2261 *vp80-04-partitions-1404.ivf
+93cc323b6b6867f1b12dd48773424549c6960a6b *vp80-04-partitions-1405.ivf
+047eedb14b865bdac8a3538e63801054e0295e9c *vp80-04-partitions-1406.ivf
+0f1233bd2bc33f56ce5e495dbd455d122339f384 *vp80-05-sharpness-1428.ivf
+51767fc136488a9535c2a4c38067c542ee2048df *vp80-05-sharpness-1429.ivf
+9805aa107672de25d6fb8c35e20d06deca5efe18 *vp80-05-sharpness-1430.ivf
+61db6b965f9c27aebe71b85bf2d5877e58e4bbdf *vp80-05-sharpness-1431.ivf
+10420d266290d2923555f84af38eeb96edbd3ae8 *vp80-05-sharpness-1433.ivf
+3ed24f9a80cddfdf75824ba95cdb4ff9286cb443 *vp80-05-sharpness-1434.ivf
+c87599cbecd72d4cd4f7ace3313b7a6bc6eb8163 *vp80-05-sharpness-1438.ivf
+aff51d865c2621b60510459244ea83e958e4baed *vp80-05-sharpness-1439.ivf
+da386e72b19b5485a6af199c5eb60ef25e510dd1 *vp80-05-sharpness-1440.ivf
+6759a095203d96ccd267ce09b1b050b8cc4c2f1f *vp80-05-sharpness-1443.ivf
+b95d3cc1d0df991e63e150a801710a72f20d9ba0 *vp80-06-smallsize.ivf
+db55ec7fd02c864ba996ff060b25b1e08611330b *vp80-00-comprehensive-001.ivf.md5
+29db0ad011cba1e45f856d5623cd38dac3e3bf19 *vp80-00-comprehensive-002.ivf.md5
+e84f258f69e173e7d68f8f8c037a0a3766902182 *vp80-00-comprehensive-003.ivf.md5
+eb7912eaf69559a16fd82bc3f5fb1524cf4a4466 *vp80-00-comprehensive-004.ivf.md5
+4206f71c94894bd5b5b376f6c09b3817dbc65206 *vp80-00-comprehensive-005.ivf.md5
+4f89b356f6f2fecb928f330a10f804f00f5325f5 *vp80-00-comprehensive-006.ivf.md5
+2813236a32964dd8007e17648bcf035a20fcda6c *vp80-00-comprehensive-007.ivf.md5
+10746c72098f872803c900e17c5680e451f5f498 *vp80-00-comprehensive-008.ivf.md5
+39a23d0692ce64421a7bb7cdf6ccec5928d37fff *vp80-00-comprehensive-009.ivf.md5
+f6e3de8931a0cc659bda8fbc14050346955e72d4 *vp80-00-comprehensive-010.ivf.md5
+101683ec195b6e944f7cd1e468fc8921439363e6 *vp80-00-comprehensive-011.ivf.md5
+1f592751ce46d8688998fa0fa4fbdcda0fd4058c *vp80-00-comprehensive-012.ivf.md5
+6066176f90ca790251e795fca1a5797d59999841 *vp80-00-comprehensive-013.ivf.md5
+2656da94ba93691f23edc4d60b3a09e2be46c217 *vp80-00-comprehensive-014.ivf.md5
+c6e0d5f5d61460c8ac8edfa4e701f10312c03133 *vp80-00-comprehensive-015.ivf.md5
+ee60fee501d8493e34e8d6a1fe315b51ed09b24a *vp80-00-comprehensive-016.ivf.md5
+9f1914ceffcad4546c0a29de3ef591d8bea304dc *vp80-00-comprehensive-017.ivf.md5
+e0305178fe288a9fd8082b39e2d03181edb19054 *vp80-00-comprehensive-018.ivf.md5
+612494da2fa799cc9d76dcdd835ae6c7cb2e5c05 *vp80-01-intra-1400.ivf.md5
+48ea06097ac8269c5e8c2131d3d0639f431fcf0e *vp80-01-intra-1411.ivf.md5
+6e2ab4e7677ad0ba868083ca6bc387ee922b400c *vp80-01-intra-1416.ivf.md5
+eca0a90348959ce3854142f8d8641b13050e8349 *vp80-01-intra-1417.ivf.md5
+920feea203145d5c2258a91c4e6991934a79a99e *vp80-02-inter-1402.ivf.md5
+f71d97909fe2b3dd65be7e1f56c72237f0cef200 *vp80-02-inter-1412.ivf.md5
+e911254569a30bbb2a237ff8b79f69ed9da0672d *vp80-02-inter-1418.ivf.md5
+58c789c50c9bb9cc90580bed291164a0939d28ba *vp80-02-inter-1424.ivf.md5
+ff3e2f441327b9c20a0b37c524e0f5a48a36de7b *vp80-03-segmentation-01.ivf.md5
+0791f417f076a542ae66fbc3426ab4d94cbd6c75 *vp80-03-segmentation-02.ivf.md5
+722e50f1a6a91c34302d68681faffc1c26d1cc57 *vp80-03-segmentation-03.ivf.md5
+c701f1885bcfb27fb8e70cc65606b289172ef889 *vp80-03-segmentation-04.ivf.md5
+f79bc9ec189a2b4807632a3d0c5bf04a178b5300 *vp80-03-segmentation-1401.ivf.md5
+b9aa4c74c0219b639811c44760d0b24cd8bb436a *vp80-03-segmentation-1403.ivf.md5
+70d5a2207ca1891bcaebd5cf6dd88ce8d57b4334 *vp80-03-segmentation-1407.ivf.md5
+265f962ee781531f9a93b9309461316fd32b2a1d *vp80-03-segmentation-1408.ivf.md5
+0c4ecbbd6dc042d30e626d951b65f460dd6cd563 *vp80-03-segmentation-1409.ivf.md5
+cf779af36a937f06570a0fca9db64ba133451dee *vp80-03-segmentation-1410.ivf.md5
+0e6c5036d51ab078842f133934926c598a9cff02 *vp80-03-segmentation-1413.ivf.md5
+eb3930aaf229116c80d507516c34759c3f6cdf69 *vp80-03-segmentation-1414.ivf.md5
+123d6c0f72ee87911c4ae7538e87b7d163b22d6c *vp80-03-segmentation-1415.ivf.md5
+e70551d1a38920e097a5d8782390b79ecaeb7505 *vp80-03-segmentation-1425.ivf.md5
+44e8f4117e46dbb302b2cfd81171cc1a1846e431 *vp80-03-segmentation-1426.ivf.md5
+52636e54aee5f95bbace37021bd67de5db767e9a *vp80-03-segmentation-1427.ivf.md5
+b1ad3eff20215c28e295b15ef3636ed926d59cba *vp80-03-segmentation-1432.ivf.md5
+24c22a552fa28a90e5978f67f57181cc2d7546d7 *vp80-03-segmentation-1435.ivf.md5
+96c49c390abfced18a7a8c9b9ea10af778e10edb *vp80-03-segmentation-1436.ivf.md5
+f95eb6214571434f1f73ab7833b9ccdf47588020 *vp80-03-segmentation-1437.ivf.md5
+1c0700ca27c9b0090a7747a4b0b4dc21d1843181 *vp80-03-segmentation-1441.ivf.md5
+81d4f23ca32667ee958bae579c8f5e97ba72eb97 *vp80-03-segmentation-1442.ivf.md5
+272efcef07a3a30fbca51bfd566063d8258ec0be *vp80-04-partitions-1404.ivf.md5
+66ed219ab812ac801b256d35cf495d193d4cf478 *vp80-04-partitions-1405.ivf.md5
+36083f37f56f502bd60ec5e07502ee9e6b8699b0 *vp80-04-partitions-1406.ivf.md5
+6ca909bf168a64c09415626294665dc1be3d1973 *vp80-05-sharpness-1428.ivf.md5
+1667d2ee2334e5fdea8a8a866f4ccf3cf76f033a *vp80-05-sharpness-1429.ivf.md5
+71bcbe5357d36a19df5b07fbe3e27bffa8893f0a *vp80-05-sharpness-1430.ivf.md5
+89a09b1dffce2d55770a89e58d9925c70ef79bf8 *vp80-05-sharpness-1431.ivf.md5
+08444a18b4e6ba3450c0796dd728d48c399a2dc9 *vp80-05-sharpness-1433.ivf.md5
+6d6223719a90c13e848aa2a8a6642098cdb5977a *vp80-05-sharpness-1434.ivf.md5
+41d70bb5fa45bc88da1604a0af466930b8dd77b5 *vp80-05-sharpness-1438.ivf.md5
+086c56378df81b6cee264d7540a7b8f2b405c7a4 *vp80-05-sharpness-1439.ivf.md5
+d32dc2c4165eb266ea4c23c14a45459b363def32 *vp80-05-sharpness-1440.ivf.md5
+8c69dc3d8e563f56ffab5ad1e400d9e689dd23df *vp80-05-sharpness-1443.ivf.md5
+d6f246df012c241b5fa6c1345019a3703d85c419 *vp80-06-smallsize.ivf.md5
+ce881e567fe1d0fbcb2d3e9e6281a1a8d74d82e0 *vp90-2-00-quantizer-00.webm
+ac5eda33407d0521c7afca43a63fd305c0cd9d13 *vp90-2-00-quantizer-00.webm.md5
+2ca0463f2cfb93d25d7dded174db70b7cb87cb48 *vp90-2-00-quantizer-01.webm
+10d98884fc6d9a5f47a2057922b8e25dd48d7786 *vp90-2-00-quantizer-01.webm.md5
+d80a2920a5e0819d69dcba8fe260c01f820f8982 *vp90-2-00-quantizer-02.webm
+c964c8e5e04165fabbf1c6ee8ee5121d35921965 *vp90-2-00-quantizer-02.webm.md5
+fdef046777b5b75c962b715d809dbe2ea331afb9 *vp90-2-00-quantizer-03.webm
+f270bee0b0c7aa2bf4c5afe098556b4f3f890faf *vp90-2-00-quantizer-03.webm.md5
+66d98609e809394a6ac730787e6724e3badc075a *vp90-2-00-quantizer-04.webm
+427433bfe121c4aea1095ec3124fdc174d200e3a *vp90-2-00-quantizer-04.webm.md5
+e6e42626d8cadf0b5be16313f69212981b96fee5 *vp90-2-00-quantizer-05.webm
+c98f6a9a1af4cfd71416792827304266aad4bd46 *vp90-2-00-quantizer-05.webm.md5
+413ef09b721f5dcec1a96e937a97e5873c2e6db6 *vp90-2-00-quantizer-06.webm
+5080e940a23805c82e578e21b57fc2c511e76376 *vp90-2-00-quantizer-06.webm.md5
+4a50a5f4ac717c30dfaae8bb46702e3542e867de *vp90-2-00-quantizer-07.webm
+76c429a02b56762e10ee4db88729d8834b3a70f4 *vp90-2-00-quantizer-07.webm.md5
+d2f4e464780bf8b7e647efa18ac777a930e62bc0 *vp90-2-00-quantizer-08.webm
+ab94aabf9316111b52d7c531962ed4123313b6ba *vp90-2-00-quantizer-08.webm.md5
+174bc58433936dd79550398d744f1072ce7f5693 *vp90-2-00-quantizer-09.webm
+e1f7690cd83ccc56d045e17cce552544a5f03810 *vp90-2-00-quantizer-09.webm.md5
+52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-00-quantizer-10.webm
+9b37bed893b5f6a4e12f2aa40f02dd40f944d0f8 *vp90-2-00-quantizer-10.webm.md5
+10031eecafde1e1d8e6323fe2b2a1d7e77a66869 *vp90-2-00-quantizer-11.webm
+fe4620a4bb0e4f5cb9bbfedc4039a22b81b0f5c0 *vp90-2-00-quantizer-11.webm.md5
+78e9f7bb77e8e348155bbdfa12790789d1d50c34 *vp90-2-00-quantizer-12.webm
+0961d060cc8dd469c6dac8d7d75f927c0bb971b8 *vp90-2-00-quantizer-12.webm.md5
+133b77a3bbcef652552d74ffc46afbfe3b8a1cba *vp90-2-00-quantizer-13.webm
+df29e5e0f95772af482f540d776f6b9dea4bfa29 *vp90-2-00-quantizer-13.webm.md5
+27323afdaf8987e025c27129c74c86502315a206 *vp90-2-00-quantizer-14.webm
+ce96a2cc312942f0427a463f15a392870dd69764 *vp90-2-00-quantizer-14.webm.md5
+ab58d0b41037829f6bc993910999f4af0212aafd *vp90-2-00-quantizer-15.webm
+40f700db606501aa7cb49049624cbdde6409b122 *vp90-2-00-quantizer-15.webm.md5
+cd948e66448aafb65998815ce37241f95d7c9ee7 *vp90-2-00-quantizer-16.webm
+039b742d149c945ed79c7b9a6384352852a1c116 *vp90-2-00-quantizer-16.webm.md5
+62f56e663e13c576764e491cf08f19bd46a71999 *vp90-2-00-quantizer-17.webm
+90c5a39bf76e6b3e0a1c0d3e9b68a9fd78be963e *vp90-2-00-quantizer-17.webm.md5
+f26ecad7263cd66a614e53ba5d7c00df181affeb *vp90-2-00-quantizer-18.webm
+cda0a1c0fca2ec2976ae55124a8a67305508bae6 *vp90-2-00-quantizer-18.webm.md5
+94bfc4c04fcfe139a63b98c569e8c14ba98c401f *vp90-2-00-quantizer-19.webm
+5b8ec169ccf67d8a0a8e46a62eb173f5a1dbaf4f *vp90-2-00-quantizer-19.webm.md5
+0ee88e9318985e1e245de78c2c4a665885ab76a7 *vp90-2-00-quantizer-20.webm
+4b26f7edb4fcd3a1b4cce9ba3cb8650e3ee6e063 *vp90-2-00-quantizer-20.webm.md5
+6a995cb2b1db33da8087321df1e646f95c3e32d1 *vp90-2-00-quantizer-21.webm
+e216b4a1eceac03efcc433759be54ab8ea87b24b *vp90-2-00-quantizer-21.webm.md5
+aa7722fc427e7180115f3c9cd96bb6b2768e7296 *vp90-2-00-quantizer-22.webm
+1aa813bd45ae831bf5e79ace4d73dfd25989a07d *vp90-2-00-quantizer-22.webm.md5
+7677e5b929ed6d142041f19b8a9cd5822ee1504a *vp90-2-00-quantizer-23.webm
+0de0af34abd843d5b37e58baf3ed96a6104b64c3 *vp90-2-00-quantizer-23.webm.md5
+b2995cbe1128b2d4926f1b28d01c501ecb6be8c8 *vp90-2-00-quantizer-24.webm
+db6033af2ba2f2bca62468fb4b8808e474f93923 *vp90-2-00-quantizer-24.webm.md5
+8135ba35587fd92cd4667be7896323d9b634401c *vp90-2-00-quantizer-25.webm
+3499e00c2cc15876f61f07e3d3cfca54ebcd98fd *vp90-2-00-quantizer-25.webm.md5
+af0fa2907746db82d345f6d831fcc1b2862a29fb *vp90-2-00-quantizer-26.webm
+cd6fe3d14dab48886ebf65be00e6ed9616ebe5a7 *vp90-2-00-quantizer-26.webm.md5
+bd0002e91323776beb5ff11e06edcf19fc08e9b9 *vp90-2-00-quantizer-27.webm
+fe72154ef196067d6c272521012dd79706496cac *vp90-2-00-quantizer-27.webm.md5
+fc15eb606f81455ff03df16bf3432296b002c43c *vp90-2-00-quantizer-28.webm
+40b2e24b542206a6bfd746ef199e49ccea07678a *vp90-2-00-quantizer-28.webm.md5
+3090bbf913cad0b2eddca7228f5ed51a58378b8d *vp90-2-00-quantizer-29.webm
+eb59745e0912d8ed6c928268bcf265237c9ba93f *vp90-2-00-quantizer-29.webm.md5
+c615abdca9c25e1cb110d908edbedfb3b7c92b91 *vp90-2-00-quantizer-30.webm
+ad0f4fe6733e4e7cdfe8ef8722bb341dcc7538c0 *vp90-2-00-quantizer-30.webm.md5
+037d9f242086cfb085518f6416259defa82d5fc2 *vp90-2-00-quantizer-31.webm
+4654b40792572f0a790874c6347ef9196d86c1a7 *vp90-2-00-quantizer-31.webm.md5
+505899f3f3515044c5c8b3213d9b9d16f614619d *vp90-2-00-quantizer-32.webm
+659a2e6dd02df323f62600626859006640b445df *vp90-2-00-quantizer-32.webm.md5
+8b32ec9c3b7e5ca8ddc6b8aea1c1cb7ca996bccc *vp90-2-00-quantizer-33.webm
+5b175ef1120ddeba4feae1247bf381bbc4e816ce *vp90-2-00-quantizer-33.webm.md5
+4d283755d17e287b1d099a80604398f60d7fb6ea *vp90-2-00-quantizer-34.webm
+22a739de95acfeb27524e3700b8f678a9ad744d8 *vp90-2-00-quantizer-34.webm.md5
+4296f56a892a412d3d4f64824718dd566c4e6459 *vp90-2-00-quantizer-35.webm
+c532c9c8dc7b3506fc6a51e5c20c17ef0ac039e7 *vp90-2-00-quantizer-35.webm.md5
+6f54e11da461e4410dd9075b015e2d9bc1d07dfb *vp90-2-00-quantizer-36.webm
+0b3573f5addea4e3eb11a0b85f068299d5bdad78 *vp90-2-00-quantizer-36.webm.md5
+210581682a26c2c4375efc785c36e07539888bc2 *vp90-2-00-quantizer-37.webm
+2b4fb6f8ba975237858e61cc8f560bcfc87cb38e *vp90-2-00-quantizer-37.webm.md5
+a15ef31283dfc4860f837fe200eb32a445f59629 *vp90-2-00-quantizer-38.webm
+fb76771f3a795054b9936f70da7505c3ac585284 *vp90-2-00-quantizer-38.webm.md5
+1df8433a441412831daae6726df89fa70d21b14d *vp90-2-00-quantizer-39.webm
+39e162c09a20e7e684868097766347014371fee6 *vp90-2-00-quantizer-39.webm.md5
+5330e4788ab9129dbb25a7a7d5411104521248b6 *vp90-2-00-quantizer-40.webm
+872cc0f2cc9dbf000f89eadb4d8f9940e48e00b1 *vp90-2-00-quantizer-40.webm.md5
+d88d03b982889e399a78d7a06eeb1cf30e6c2da2 *vp90-2-00-quantizer-41.webm
+5b4f7217e57fa2a221011d0b32f8d0409496b7b6 *vp90-2-00-quantizer-41.webm.md5
+9e16406e3e26955a6e17d455ef1ef64bbfa26e53 *vp90-2-00-quantizer-42.webm
+0219d090cf37daabe19256ba8e932ba4874b92e4 *vp90-2-00-quantizer-42.webm.md5
+a9b15843486fb05f8cd15437ef279782a42b75db *vp90-2-00-quantizer-43.webm
+3c9b0b4c607f9579a31726bfcf56729334ddc686 *vp90-2-00-quantizer-43.webm.md5
+1dbc931ac446c91eabe7213efff55b596cccf07c *vp90-2-00-quantizer-44.webm
+73bc8f675103abaef3d9f73a2742b3bffd726d23 *vp90-2-00-quantizer-44.webm.md5
+7c6c1be15beb9d6201204b018966c8c4f9777efc *vp90-2-00-quantizer-45.webm
+c907b29da821f790c6748de61f592689312e4e36 *vp90-2-00-quantizer-45.webm.md5
+07b434da1a467580f73b32177ee11b3e00f65a0d *vp90-2-00-quantizer-46.webm
+7b2b7ce60c50bc970bc0ada46d7a7ce440148da3 *vp90-2-00-quantizer-46.webm.md5
+233d0465fb1a6fa36e9f89bd2193ac79bd4d2809 *vp90-2-00-quantizer-47.webm
+527e0a9fb932efe915027ffe077f9e8d3a4fb139 *vp90-2-00-quantizer-47.webm.md5
+719613df7307e205c3fdb6acfb373849c5ab23c7 *vp90-2-00-quantizer-48.webm
+65ab6c9d1b682c183b201c7ff42b90343ce3e304 *vp90-2-00-quantizer-48.webm.md5
+3bf04a598325ed0eabae1598ec7f718f715ec672 *vp90-2-00-quantizer-49.webm
+ac68c4387ce11fcc998d8ba455ab9b2bb361d240 *vp90-2-00-quantizer-49.webm.md5
+d59238fb3a654931c9b65a11e7321b40d1f702e9 *vp90-2-00-quantizer-50.webm
+d0576bfede46fd55659f028f2fd28554ceb3e6cc *vp90-2-00-quantizer-50.webm.md5
+3f579785101d4209360dd96f8c2ffe9beddf3bee *vp90-2-00-quantizer-51.webm
+89fcfe04f4457a7f02ab4a2f94aacbb88aee5789 *vp90-2-00-quantizer-51.webm.md5
+28be5836e2fedefe4babf12fc9b79e460ab0a0f4 *vp90-2-00-quantizer-52.webm
+f3dd52b70c18345fee740220f35da9c4def2017a *vp90-2-00-quantizer-52.webm.md5
+488ad4058c17170665b6acd1021fade9a02771e4 *vp90-2-00-quantizer-53.webm
+1cdcb1d4f3a37cf83ad235eb27ec62ed2a01afc7 *vp90-2-00-quantizer-53.webm.md5
+682978289cb28cc8c9d39bc797300e45d6039de7 *vp90-2-00-quantizer-54.webm
+36c35353f2c03cb099bd710d9994de7d9ed88834 *vp90-2-00-quantizer-54.webm.md5
+c398ce49af762a48f10cc4da9fae0769aae5f226 *vp90-2-00-quantizer-55.webm
+2cf3570542d984f167ab087f59493c7fb47e0ed2 *vp90-2-00-quantizer-55.webm.md5
+3071f18b2fce261aa82d61f81a7ae4ca9a75d0e3 *vp90-2-00-quantizer-56.webm
+d3f93f8272b6de31cffb011a26f11abb514efb12 *vp90-2-00-quantizer-56.webm.md5
+f4e8e14b1f278801a7eb6f11734780a01b1668e9 *vp90-2-00-quantizer-57.webm
+6478fdf1d7faf6db5f19dffc5e1363af358699ee *vp90-2-00-quantizer-57.webm.md5
+307dc264f57cc618fff211fa44d7f52767ed9660 *vp90-2-00-quantizer-58.webm
+cf231d4a52d492fa692ea4194ec5eb7511fec54e *vp90-2-00-quantizer-58.webm.md5
+1fd7cd596170afce2de0b1441b7674bda5723440 *vp90-2-00-quantizer-59.webm
+4681f7ef96f63e085c41bb1a964b0df7e67e0b38 *vp90-2-00-quantizer-59.webm.md5
+34cdcc81c0ba7085aefbb22d7b4aa9bca3dd7c62 *vp90-2-00-quantizer-60.webm
+58691ef53b6b623810e2c57ded374c77535df935 *vp90-2-00-quantizer-60.webm.md5
+e6e812406aab81021bb16e772c1db03f75906cb6 *vp90-2-00-quantizer-61.webm
+76436eace62f08ff92b61a0845e66667a027db1b *vp90-2-00-quantizer-61.webm.md5
+84d811bceed70c950a6a08e572a6e274866e72b1 *vp90-2-00-quantizer-62.webm
+2d937cc011eeddd95222b960982da5cd18db580f *vp90-2-00-quantizer-62.webm.md5
+0912b295ba0ea09359315315ffd67d22d046f883 *vp90-2-00-quantizer-63.webm
+5a829031055d70565f57dbcd47a6ac33619952b3 *vp90-2-00-quantizer-63.webm.md5
+0cf9e5ebe0112bdb47b5887ee5d58eb9d4727c00 *vp90-2-01-sharpness-1.webm
+5a0476be4448bae8f8ca17ea236c98793a755948 *vp90-2-01-sharpness-1.webm.md5
+51e02d7911810cdf5be8b68ac40aedab479a3179 *vp90-2-01-sharpness-2.webm
+a0ca5bc87a5ed7c7051f59078daa0d03be1b45b6 *vp90-2-01-sharpness-2.webm.md5
+0603f8ad239c07a531d948187f4dafcaf51eda8d *vp90-2-01-sharpness-3.webm
+3af8000a69c72fe77881e3176f026c2affb78cc7 *vp90-2-01-sharpness-3.webm.md5
+4ca4839f48146252fb261ed88838d80211804841 *vp90-2-01-sharpness-4.webm
+08832a1494f84fa9edd40e080bcf2c0e80100c76 *vp90-2-01-sharpness-4.webm.md5
+95099dc8f9cbaf9b9a7dd65311923e441ff70731 *vp90-2-01-sharpness-5.webm
+93ceee30c140f0b406726c0d896b9db6031c4c7f *vp90-2-01-sharpness-5.webm.md5
+ceb4116fb7b078d266d153233b6d62a255a34e4c *vp90-2-01-sharpness-6.webm
+da83efe59e537ce538e8b03a6eac63cf25849c9a *vp90-2-01-sharpness-6.webm.md5
+b5f7cd19aece3880f9d616a778e5cc24c6b9b505 *vp90-2-01-sharpness-7.webm
+2957408d20deac8633941a2169f801bae6f086e1 *vp90-2-01-sharpness-7.webm.md5
+ffc096c2ce1050450ad462b5fabd2a5220846319 *vp90-2-02-size-08x08.webm
+e36d2ed6fa2746347710b750586aafa6a01ff3ae *vp90-2-02-size-08x08.webm.md5
+895b986f9fd55cd879472b31c6a06b82094418c8 *vp90-2-02-size-08x10.webm
+079157a19137ccaebba606f2871f45a397347150 *vp90-2-02-size-08x10.webm.md5
+1c5992203e62a2b83040ccbecd748b604e19f4c0 *vp90-2-02-size-08x16.webm
+9aa45ffdf2078f883bbed01450031b691819c144 *vp90-2-02-size-08x16.webm.md5
+d0a8953da1f85f484487408fee5da9e2a8391901 *vp90-2-02-size-08x18.webm
+59a5cc17d354c6a23e5e959d666b1456a5d49c56 *vp90-2-02-size-08x18.webm.md5
+1b13461a9fc65cb041bacfe4ea6f02d363397d61 *vp90-2-02-size-08x32.webm
+2bdddd6878f05d37d84cde056a3f5e7f926ba3d6 *vp90-2-02-size-08x32.webm.md5
+2861f0a0daadb62295b0504a1fbe5b50c79a8f59 *vp90-2-02-size-08x34.webm
+6b5812cfb8a82d378ea2913bf009e93668020147 *vp90-2-02-size-08x34.webm.md5
+02f948216d4246579dc53c47fe55d8fb264ba251 *vp90-2-02-size-08x64.webm
+84b55fdee6d9aa820c7a8c62822446184b191767 *vp90-2-02-size-08x64.webm.md5
+4b011242cbf42516efd2b197baebb61dd34562c9 *vp90-2-02-size-08x66.webm
+6b1fa0a885947b3cc0fe58f75f838e662bd9bb8b *vp90-2-02-size-08x66.webm.md5
+4057796be9dd12df48ab607f502ae6aa70eeeab6 *vp90-2-02-size-10x08.webm
+71c752c51aec9f48de286b93f4c20e9c11cad7d0 *vp90-2-02-size-10x08.webm.md5
+6583c853fa43fc53d51743eac5f3a43a359d45d0 *vp90-2-02-size-10x10.webm
+1da524d24af1944b671d4d3f2b398d6e336584c3 *vp90-2-02-size-10x10.webm.md5
+ba442fc03ccd3a705c64c83b36f5ada67d198874 *vp90-2-02-size-10x16.webm
+7cfd960f232c34c641a4a2a9411b6fd0efb2fc50 *vp90-2-02-size-10x16.webm.md5
+cc92ed40eef14f52e4d080cb2c57939dd8326374 *vp90-2-02-size-10x18.webm
+db5626275cc55ce970b91c995e74f6838d943aca *vp90-2-02-size-10x18.webm.md5
+3a93d501d22325e9fd4c9d8b82e2a432de33c351 *vp90-2-02-size-10x32.webm
+5cae51b0c71cfc131651f345f87583eb2903afaf *vp90-2-02-size-10x32.webm.md5
+50d2f2b15a9a5178153db44a9e03aaf32b227f67 *vp90-2-02-size-10x34.webm
+bb0efe058122641e7f73e94497dda2b9e6c21efd *vp90-2-02-size-10x34.webm.md5
+01624ec173e533e0b33fd9bdb91eb7360c7c9175 *vp90-2-02-size-10x64.webm
+b9c0e3b054463546356acf5157f9be92fd34732f *vp90-2-02-size-10x64.webm.md5
+2942879baf1c09e96b14d0fc84806abfe129c706 *vp90-2-02-size-10x66.webm
+bab5f539c2f91952e187456b4beafbb4c01e25ee *vp90-2-02-size-10x66.webm.md5
+88d2b63ca5e9ee163d8f20e8886f3df3ff301a66 *vp90-2-02-size-16x08.webm
+7f48a0fcf8c25963f3057d7f6669c5f2415834b8 *vp90-2-02-size-16x08.webm.md5
+59261eb34c15ea9b5ddd2d416215c1a8b9e6dc1f *vp90-2-02-size-16x10.webm
+73a7c209a46dd051c9f7339b6e02ccd5b3b9fc81 *vp90-2-02-size-16x10.webm.md5
+066834fef9cf5b9a72932cf4dea5f253e14a976d *vp90-2-02-size-16x16.webm
+faec542f52f37601cb9c480d887ae9355be99372 *vp90-2-02-size-16x16.webm.md5
+195307b4eb3192271ee4a935b0e48deef0c54cc2 *vp90-2-02-size-16x18.webm
+5a92e19e624c0376321d4d0e22c0c91995bc23e1 *vp90-2-02-size-16x18.webm.md5
+14f3f884216d7ae16ec521f024a2f2d31bbf9c1a *vp90-2-02-size-16x32.webm
+ea622d1c817dd174556f7ee7ccfe4942b34d4845 *vp90-2-02-size-16x32.webm.md5
+2e0501100578a5da9dd47e4beea160f945bdd1ba *vp90-2-02-size-16x34.webm
+1b8645ef64239334921c5f56b24ce815e6070b05 *vp90-2-02-size-16x34.webm.md5
+89a6797fbebebe93215f367229a9152277f5dcfe *vp90-2-02-size-16x64.webm
+a03d8c1179ca626a8856fb416d635dbf377979cd *vp90-2-02-size-16x64.webm.md5
+0f3a182e0750fcbae0b9eae80c7a53aabafdd18d *vp90-2-02-size-16x66.webm
+8cb6736dc2d897c1283919a32068af377d66c59c *vp90-2-02-size-16x66.webm.md5
+68fe70dc7914cc1d8d6dcd97388b79196ba3e7f1 *vp90-2-02-size-18x08.webm
+874c7fb505be9db3160c57cb405c4dbd5b990dc2 *vp90-2-02-size-18x08.webm.md5
+0546352dd78496d4dd86c3727ac2ff36c9e72032 *vp90-2-02-size-18x10.webm
+1d80eb36557ea5f25a386495a36f93da0f25316b *vp90-2-02-size-18x10.webm.md5
+60fe99e5f5cc99706efa3e0b894e45cbcf0d6330 *vp90-2-02-size-18x16.webm
+1ab6cdd89a53662995d103546e6611c84f9292ab *vp90-2-02-size-18x16.webm.md5
+f9a8f5fb749d69fd555db6ca093b7f77800c7b4f *vp90-2-02-size-18x18.webm
+ace8a66328f7802b15f9989c2720c029c6abd279 *vp90-2-02-size-18x18.webm.md5
+a197123a527ec25913a9bf52dc8c347749e00045 *vp90-2-02-size-18x32.webm
+34fbd7036752232d1663e70d7f7cdc93f7129202 *vp90-2-02-size-18x32.webm.md5
+f219655a639a774a2c9c0a9f45c28dc0b5e75e24 *vp90-2-02-size-18x34.webm
+2c4d622a9ea548791c1a07903d3702e9774388bb *vp90-2-02-size-18x34.webm.md5
+5308578da48c677d477a5404e19391d1303033c9 *vp90-2-02-size-18x64.webm
+e7fd4462527bac38559518ba80e41847db880f15 *vp90-2-02-size-18x64.webm.md5
+e109a7e013bd179f97e378542e1e81689ed06802 *vp90-2-02-size-18x66.webm
+45c04e422fb383c1f3be04beefaa4490e83bdb1a *vp90-2-02-size-18x66.webm.md5
+38844cae5d99caf445f7de33c3ae78494ce36c01 *vp90-2-02-size-32x08.webm
+ad018be39e493ca2405225034b1a5b7a42af6f3a *vp90-2-02-size-32x08.webm.md5
+7b57eaad55906f9de9903c8657a3fcb2aaf792ea *vp90-2-02-size-32x10.webm
+2294425d4e55d275af5e25a0beac9738a1b4ee73 *vp90-2-02-size-32x10.webm.md5
+f47ca2ced0d47f761bb0a5fdcd911d3f450fdcc1 *vp90-2-02-size-32x16.webm
+ae10981d93913f0ab1f28c1146255e01769aa8c0 *vp90-2-02-size-32x16.webm.md5
+08b23ad838b6cf1fbfe3ad7e7775d95573e815fc *vp90-2-02-size-32x18.webm
+1ba76f4c4a4ac7aabfa3ce195c1b473535eb7cc8 *vp90-2-02-size-32x18.webm.md5
+d5b88ae6c8c25c53dee74d9f1e6ca64244349a57 *vp90-2-02-size-32x32.webm
+e39c067a8ee2da52a51641eb1cb7f8eba935eb6b *vp90-2-02-size-32x32.webm.md5
+529429920dc36bd899059fa75a767f02c8c60874 *vp90-2-02-size-32x34.webm
+56888e7834f52b106e8911e3a7fc0f473b609995 *vp90-2-02-size-32x34.webm.md5
+38e848e160391c2b1a55040aadde613b9f4bf15e *vp90-2-02-size-32x64.webm
+8950485fb3f68b0e8be234db860e4ec5f5490fd0 *vp90-2-02-size-32x64.webm.md5
+5e8670f0b8ec9cefa8795b8959ffbe1a8e1aea94 *vp90-2-02-size-32x66.webm
+225df9d7d72ec711b0b60f4aeb65311c97db054a *vp90-2-02-size-32x66.webm.md5
+695f929e2ce6fb11a1f180322d46c5cb1c97fa61 *vp90-2-02-size-34x08.webm
+5bb4262030018dd01883965c6aa6070185924ef6 *vp90-2-02-size-34x08.webm.md5
+5adf74ec906d2ad3f7526e06bd29f5ad7d966a90 *vp90-2-02-size-34x10.webm
+71c100b437d3e8701632ae8d65c3555339b1c68f *vp90-2-02-size-34x10.webm.md5
+d0918923c987fba2d00193d83797b21289fe54aa *vp90-2-02-size-34x16.webm
+5d5a52f3535b4d2698dd3d87f4a13fdc9b57163d *vp90-2-02-size-34x16.webm.md5
+553ab0042cf87f5e668ec31b2e4b2a4b6ec196fd *vp90-2-02-size-34x18.webm
+a164c7f3c424987df2340496e6a8cf76e973f0f1 *vp90-2-02-size-34x18.webm.md5
+baf3e233634f150de81c18ba5d8848068e1c3c54 *vp90-2-02-size-34x32.webm
+22a79d3bd1c9b85dfe8c70bb2e19f08a92a8be03 *vp90-2-02-size-34x32.webm.md5
+6d50a533774a7167350e4a7ef43c94a5622179a2 *vp90-2-02-size-34x34.webm
+0c099638e79c273546523e06704553e42eb00b00 *vp90-2-02-size-34x34.webm.md5
+698cdd0a5e895cc202c488675e682a8c537ede4f *vp90-2-02-size-34x64.webm
+9317b63987cddab8389510a27b86f9f3d46e3fa5 *vp90-2-02-size-34x64.webm.md5
+4b5335ca06f082b6b69f584eb8e7886bdcafefd3 *vp90-2-02-size-34x66.webm
+e18d68b35428f46a84a947c646804a51ef1d7cec *vp90-2-02-size-34x66.webm.md5
+a54ae7b494906ec928a876e8290e5574f2f9f6a2 *vp90-2-02-size-64x08.webm
+87f9f7087b6489d45e9e4b38ede2c5aef4a4928f *vp90-2-02-size-64x08.webm.md5
+24522c70804a3c23d937df2d829ae63965b23f38 *vp90-2-02-size-64x10.webm
+447ce03938ab53bffcb4a841ee0bfaa90462dcb9 *vp90-2-02-size-64x10.webm.md5
+2a5035d035d214ae614af8051930690ef623989b *vp90-2-02-size-64x16.webm
+84e355761dd2e0361b904c84c52a0dd0384d89cf *vp90-2-02-size-64x16.webm.md5
+3a293ef4e270a19438e59b817fbe5f43eed4d36b *vp90-2-02-size-64x18.webm
+666824e5ba746779eb46079e0631853dcc86d48b *vp90-2-02-size-64x18.webm.md5
+ed32fae837095c9e8fc95d223ec68101812932c2 *vp90-2-02-size-64x32.webm
+97086eadedce1d0d9c072b585ba7b49aec69b1e7 *vp90-2-02-size-64x32.webm.md5
+696c7a7250bdfff594f4dfd88af34239092ecd00 *vp90-2-02-size-64x34.webm
+253a1d38d452e7826b086846c6f872f829c276bb *vp90-2-02-size-64x34.webm.md5
+fc508e0e3c2e6872c60919a60b812c5232e9c2b0 *vp90-2-02-size-64x64.webm
+2cd6ebeca0f82e9f505616825c07950371b905ab *vp90-2-02-size-64x64.webm.md5
+0f8a4fc1d6521187660425c283f08dff8c66e476 *vp90-2-02-size-64x66.webm
+5806be11a1d346be235f88d3683e69f73746166c *vp90-2-02-size-64x66.webm.md5
+273b0c36e3658685cde250408a478116d7ae92f1 *vp90-2-02-size-66x08.webm
+23c3cd0dca20a2f71f036e77ea92025ff4e7a298 *vp90-2-02-size-66x08.webm.md5
+4844c59c3306d1e671bb0568f00e344bf797e66e *vp90-2-02-size-66x10.webm
+e041eaf6841d775f8fde8bbb4949d2733fdaab7f *vp90-2-02-size-66x10.webm.md5
+bdf3f1582b234fcd2805ffec59f9d716a2345302 *vp90-2-02-size-66x16.webm
+2ec85ee18119e6798968571ea6e1b93ca386e3af *vp90-2-02-size-66x16.webm.md5
+0acce9af12b13b025d5274013da7ef6f568f075f *vp90-2-02-size-66x18.webm
+77c4d53e2a5c96b70af9d575fe6811e0f5ee627b *vp90-2-02-size-66x18.webm.md5
+682b36a25774bbdedcd603f504d18eb63f0167d4 *vp90-2-02-size-66x32.webm
+53728fae2a428f16d376a29f341a64ddca97996a *vp90-2-02-size-66x32.webm.md5
+e71b70e901e29eaa6672a6aa4f37f6f5faa02bd6 *vp90-2-02-size-66x34.webm
+f69a6a555e3f614b0a35f9bfc313d8ebb35bc725 *vp90-2-02-size-66x34.webm.md5
+4151b8c29452d5c2266397a7b9bf688899a2937b *vp90-2-02-size-66x64.webm
+69486e7fd9e380b6c97a03d3e167affc79f73840 *vp90-2-02-size-66x64.webm.md5
+68784a1ecac776fe2a3f230345af32f06f123536 *vp90-2-02-size-66x66.webm
+7f008c7f48d55e652fbd6bac405b51e0015c94f2 *vp90-2-02-size-66x66.webm.md5
+7e1bc449231ac1c5c2a11c9a6333b3e828763798 *vp90-2-03-size-196x196.webm
+6788a561466dace32d500194bf042e19cccc35e1 *vp90-2-03-size-196x196.webm.md5
+a170c9a88ec1dd854c7a471ff55fb2a97ac31870 *vp90-2-03-size-196x198.webm
+6bf9d6a8e2bdc5bf4f8a78071a3fed5ca02ad6f2 *vp90-2-03-size-196x198.webm.md5
+68f861d21c4c8b03d572c3d3fcd9f4fbf1f4503f *vp90-2-03-size-196x200.webm
+bbfc260b2bfd872cc6054272bb6b7f959a9e1c6e *vp90-2-03-size-196x200.webm.md5
+fc34889feeca2b7e5b27b4f1ce22d2e2b8e3e4b1 *vp90-2-03-size-196x202.webm
+158ee72af578f39aad0c3b8f4cbed2fc78b57e0f *vp90-2-03-size-196x202.webm.md5
+dd28fb7247af534bdf5e6795a3ac429610489a0b *vp90-2-03-size-196x208.webm
+7546be847efce2d1c0a23f807bfb03f91b764e1e *vp90-2-03-size-196x208.webm.md5
+41d5cf5ed65b722a1b6dc035e67f978ea8ffecf8 *vp90-2-03-size-196x210.webm
+9444fdf632d6a1b6143f4cb10fed8f63c1d67ec1 *vp90-2-03-size-196x210.webm.md5
+5007bc618143437c009d6dde5fc2e86f72d37dc2 *vp90-2-03-size-196x224.webm
+858361d8f79b44df5545feabbc9754ec9ede632f *vp90-2-03-size-196x224.webm.md5
+0bcbe357fbc776c3fa68e7117179574ed7564a44 *vp90-2-03-size-196x226.webm
+72006a5f42031a43d70a2cd9fc1958962a86628f *vp90-2-03-size-196x226.webm.md5
+000239f048cceaac055558e97ef07078ebf65502 *vp90-2-03-size-198x196.webm
+2d6841901b72000c5340f30be602853438c1b787 *vp90-2-03-size-198x196.webm.md5
+ae75b766306a6404c3b3b35a6b6d53633c14fbdb *vp90-2-03-size-198x198.webm
+3f2544b4f3b4b643a98f2c3b15ea5826fc702fa1 *vp90-2-03-size-198x198.webm.md5
+95ffd573fa84ccef1cd59e1583e6054f56a5c83d *vp90-2-03-size-198x200.webm
+5d537e3c9b9c54418c79677543454c4cda3de1af *vp90-2-03-size-198x200.webm.md5
+ecc845bf574375f469bc91bf5c75c79dc00073d6 *vp90-2-03-size-198x202.webm
+1b59f5e111265615a7a459eeda8cc9045178d228 *vp90-2-03-size-198x202.webm.md5
+432fb27144fe421b9f51cf44d2750a26133ed585 *vp90-2-03-size-198x208.webm
+a58a67f4fb357c73ca078aeecbc0f782975630b1 *vp90-2-03-size-198x208.webm.md5
+ff5058e7e6a47435046612afc8536f2040989e6f *vp90-2-03-size-198x210.webm
+18d3be7935e52217e2e9400b6f2c681a9e45dc89 *vp90-2-03-size-198x210.webm.md5
+a0d55263c1ed2c03817454dd4ec4090d36dbc864 *vp90-2-03-size-198x224.webm
+efa366a299817e2da51c00623b165aab9fbb8d91 *vp90-2-03-size-198x224.webm.md5
+ccd142fa2920fc85bb753f049160c1c353ad1574 *vp90-2-03-size-198x226.webm
+534524a0b2dbff852e0b92ef09939db072f83243 *vp90-2-03-size-198x226.webm.md5
+0d483b94ed40abc8ab6e49f960432ee54ad9c7f1 *vp90-2-03-size-200x196.webm
+41795f548181717906e7a504ba551f06c32102ae *vp90-2-03-size-200x196.webm.md5
+f6c2dc54e0989d50f01333fe40c91661fcbf849a *vp90-2-03-size-200x198.webm
+43df5d8c46a40089441392e6d096c588c1079a68 *vp90-2-03-size-200x198.webm.md5
+2f6e9df82e44fc145f0d9212dcccbed3de605e23 *vp90-2-03-size-200x200.webm
+757b2ef96b82093255725bab9690bbafe27f3caf *vp90-2-03-size-200x200.webm.md5
+40c5ea60415642a4a2e75c0d127b06309baadfab *vp90-2-03-size-200x202.webm
+3022c4a1c625b5dc04fdb1052d17d45b4171cfba *vp90-2-03-size-200x202.webm.md5
+6942ed5b27476bb8506d10e600d6ff60887780ca *vp90-2-03-size-200x208.webm
+c4ab8c66f3cf2dc8e8dd7abae9ac21f4d32cd6be *vp90-2-03-size-200x208.webm.md5
+71dbc99b83c49d1da45589b91eabb98e2f4a7b1e *vp90-2-03-size-200x210.webm
+3f0b40da7eef7974b9bc326562f251feb67d9c7c *vp90-2-03-size-200x210.webm.md5
+6b6b8489081cfefb377cc5f18eb754ec2383f655 *vp90-2-03-size-200x224.webm
+a259df2ac0e294492e3f9d4315baa34cab044f04 *vp90-2-03-size-200x224.webm.md5
+c9adc1c9bb07559349a0b054df4af56f7a6edbb9 *vp90-2-03-size-200x226.webm
+714cec61e3575581e4f1a0e3921f4dfdbbd316c5 *vp90-2-03-size-200x226.webm.md5
+f9bdc936bdf53f8be9ce78fecd41a21d31ff3943 *vp90-2-03-size-202x196.webm
+5b8e2e50fcea2c43b12fc067b8a9cc117af77bda *vp90-2-03-size-202x196.webm.md5
+c7b66ea3da87613deb47ff24a111247d3c384fec *vp90-2-03-size-202x198.webm
+517e91204b25586da943556f4adc5951c9be8bee *vp90-2-03-size-202x198.webm.md5
+935ef56b01cfdb4265a7e24696645209ccb20970 *vp90-2-03-size-202x200.webm
+55b8ec4a2513183144a8e27564596c06c7576fce *vp90-2-03-size-202x200.webm.md5
+849acf75e4f1d8d90046704e1103a18c64f30e35 *vp90-2-03-size-202x202.webm
+c79afc6660df2824e7df314e5bfd71f0d8acf76b *vp90-2-03-size-202x202.webm.md5
+17b3a4d55576b770626ccb856b9f1a6c8f6ae476 *vp90-2-03-size-202x208.webm
+0b887ff30409c58f2ccdc3bfacd6be7c69f8997a *vp90-2-03-size-202x208.webm.md5
+032d0ade4230fb2eef6d19915a7a1c9aa4a52617 *vp90-2-03-size-202x210.webm
+f78f8e79533c0c88dd2bfdcec9b1c07848568ece *vp90-2-03-size-202x210.webm.md5
+915a38c31fe425d5b93c837121cfa8082f5ea5bc *vp90-2-03-size-202x224.webm
+bf52a104074d0c5942aa7a5b31e11db47e43d48e *vp90-2-03-size-202x224.webm.md5
+be5cfde35666fa435e47d544d9258215beb1cf29 *vp90-2-03-size-202x226.webm
+2fa2f87502fda756b319389c8975204e130a2e3f *vp90-2-03-size-202x226.webm.md5
+15d908e97862b5b4bf295610df011fb9aa09909b *vp90-2-03-size-208x196.webm
+50c60792305d6a99be376dd596a6ff979325e6cc *vp90-2-03-size-208x196.webm.md5
+a367c7bc9fde56d6f4848cc573c7d4c1ce75e348 *vp90-2-03-size-208x198.webm
+be85fb2c8d435a75484231356f07d06ebddd13cd *vp90-2-03-size-208x198.webm.md5
+05fd46deb7288e7253742091f56e54a9a441a187 *vp90-2-03-size-208x200.webm
+74f8ec3b3a2fe81767ed1ab36a47bc0062d6223c *vp90-2-03-size-208x200.webm.md5
+d8985c4b386513a7385a4b3639bf91e469f1378b *vp90-2-03-size-208x202.webm
+0614a1e8d92048852adcf605a51333f5fabc7f03 *vp90-2-03-size-208x202.webm.md5
+28b002242238479165ba4fb87ee6b442c64b32e4 *vp90-2-03-size-208x208.webm
+37de5aca59bb900228400b0e115d3229edb9dcc0 *vp90-2-03-size-208x208.webm.md5
+c545be0050c2fad7c68427dbf86c62a739e94ab3 *vp90-2-03-size-208x210.webm
+d646eccb3cd578f94b54777e32b88898bef6e17a *vp90-2-03-size-208x210.webm.md5
+63a0cfe295b661026dd7b1bebb67acace1db766f *vp90-2-03-size-208x224.webm
+85c0361d93bf85a335248fef2767ff43eeef23db *vp90-2-03-size-208x224.webm.md5
+f911cc718d66e4fe8a865226088939c9eb1b7825 *vp90-2-03-size-208x226.webm
+a6d583a57876e7b7ec48625b2b2cdbcf70cab837 *vp90-2-03-size-208x226.webm.md5
+5bbb0f36da9a4683cf04e724124d8696332911bf *vp90-2-03-size-210x196.webm
+a3580fc7816d7fbcfb54fdba501cabbd06ba2f1d *vp90-2-03-size-210x196.webm.md5
+8db64d6f9ce36dd382013b42ae4e292deba697bc *vp90-2-03-size-210x198.webm
+eda20f8268c7f4147bead4059e9c4897e09140a9 *vp90-2-03-size-210x198.webm.md5
+ce391505eeaf1d12406563101cd6b2dbbbb44bfc *vp90-2-03-size-210x200.webm
+79d73b7f623082d2a00aa33e95c79d11c7d9c3a8 *vp90-2-03-size-210x200.webm.md5
+852db6fdc206e72391fc69b807f1954934679949 *vp90-2-03-size-210x202.webm
+f69414c5677ed2f2b8b37ae76429e509a92276a5 *vp90-2-03-size-210x202.webm.md5
+c424cc3edd2308da7d33f27acb36b54db5bf2595 *vp90-2-03-size-210x208.webm
+27b18562faa1b3184256f4eae8114b539b3e9d3e *vp90-2-03-size-210x208.webm.md5
+dd029eba719d50a2851592fa8b9b2efe88904930 *vp90-2-03-size-210x210.webm
+c853a1670465eaa04ca31b3511995f1b6ed4f58f *vp90-2-03-size-210x210.webm.md5
+d962e8ae676c54d0c3ea04ec7c04b37ae6a786e3 *vp90-2-03-size-210x224.webm
+93b793e79d987065b39ad8e2e71244368435fc25 *vp90-2-03-size-210x224.webm.md5
+3d0825fe83bcc125be1f78145ff43ca6d7588784 *vp90-2-03-size-210x226.webm
+5230f31a57ca3b5311698a12035d2644533b3ec4 *vp90-2-03-size-210x226.webm.md5
+6622f8bd9279e1ce45509a58a31a990052d45e14 *vp90-2-03-size-224x196.webm
+65411da07f60113f2be05c807879072b161d561e *vp90-2-03-size-224x196.webm.md5
+6744ff2ee2c41eb08c62ff30880833b6d77b585b *vp90-2-03-size-224x198.webm
+46ea3641d41acd4bff347b224646c060d5620385 *vp90-2-03-size-224x198.webm.md5
+8eb91f3416a1404705f370caecd74b2b458351b1 *vp90-2-03-size-224x200.webm
+196aefb854c8b95b9330263d6690b7ee15693ecf *vp90-2-03-size-224x200.webm.md5
+256a5a23ef4e6d5ef2871af5afb8cd13d28cec00 *vp90-2-03-size-224x202.webm
+840ad8455dcf2be378c14b007e66fa642fc8196d *vp90-2-03-size-224x202.webm.md5
+db4606480ab48b96c9a6ff5e639f1f1aea2a12e4 *vp90-2-03-size-224x208.webm
+40b9801d5620467499ac70fa6b7c40aaa5e1c331 *vp90-2-03-size-224x208.webm.md5
+e37159e687fe1cb24cffddfae059301adbaf4212 *vp90-2-03-size-224x210.webm
+1e4acd4b6334ae260c3eed08652d0ba8122073f2 *vp90-2-03-size-224x210.webm.md5
+0de1eb4bb6285ae621e4f2b613d2aa4a8c95a130 *vp90-2-03-size-224x224.webm
+37db449ad86fb286c2c02d94aa8fe0379c05044a *vp90-2-03-size-224x224.webm.md5
+32ebbf903a7d7881bcfe59639f1d472371f3bf27 *vp90-2-03-size-224x226.webm
+5cc3ac5dc9f6912491aa2ddac863f8187f34c569 *vp90-2-03-size-224x226.webm.md5
+9480ff5c2c32b1870ac760c87514912616e6cf01 *vp90-2-03-size-226x196.webm
+fe83655c0f1888f0af7b047785f01ba7ca9f1324 *vp90-2-03-size-226x196.webm.md5
+09cad4221996315cdddad4e502dbfabf53ca1d6a *vp90-2-03-size-226x198.webm
+e3ddfdc650acb95adb45abd9b634e1f09ea8ac96 *vp90-2-03-size-226x198.webm.md5
+c34f49d55fe39e3f0b607e3cc95e30244225cecb *vp90-2-03-size-226x200.webm
+abb83edc868a3523ccd4e5523fac2efbe7c3df1f *vp90-2-03-size-226x200.webm.md5
+d17bc08eedfc60c4c23d576a6c964a21bf854d1f *vp90-2-03-size-226x202.webm
+1d22d2d0f375251c2d5a1acb4714bc35d963865b *vp90-2-03-size-226x202.webm.md5
+9bd537c4f92a25596ccd29fedfe181feac948b92 *vp90-2-03-size-226x208.webm
+6feb0e7325386275719f3511ada9e248a2ae7df4 *vp90-2-03-size-226x208.webm.md5
+4487067f6cedd495b93696b44b37fe0a3e7eda14 *vp90-2-03-size-226x210.webm
+49a8fa87945f47208168d541c068e78d878075d5 *vp90-2-03-size-226x210.webm.md5
+559fea2f8da42b33c1aa1dbc34d1d6781009847a *vp90-2-03-size-226x224.webm
+83c6d8f2969b759e10e5c6542baca1265c874c29 *vp90-2-03-size-226x224.webm.md5
+fe0af2ee47b1e5f6a66db369e2d7e9d870b38dce *vp90-2-03-size-226x226.webm
+94ad19b8b699cea105e2ff18f0df2afd7242bcf7 *vp90-2-03-size-226x226.webm.md5
+52bc1dfd3a97b24d922eb8a31d07527891561f2a *vp90-2-03-size-352x288.webm
+3084d6d0a1eec22e85a394422fbc8faae58930a5 *vp90-2-03-size-352x288.webm.md5
+b6524e4084d15b5d0caaa3d3d1368db30cbee69c *vp90-2-03-deltaq.webm
+65f45ec9a55537aac76104818278e0978f94a678 *vp90-2-03-deltaq.webm.md5
+4dbb87494c7f565ffc266c98d17d0d8c7a5c5aba *vp90-2-05-resize.ivf
+7f6d8879336239a43dbb6c9f13178cb11cf7ed09 *vp90-2-05-resize.ivf.md5
+bf61ddc1f716eba58d4c9837d4e91031d9ce4ffe *vp90-2-06-bilinear.webm
+f6235f937552e11d8eb331ec55da6b3aa596b9ac *vp90-2-06-bilinear.webm.md5
+0c83a1e414fde3bccd6dc451bbaee68e59974c76 *vp90-2-07-frame_parallel.webm
+e5c2c9fb383e5bf3b563480adaeba5b7e3475ecd *vp90-2-07-frame_parallel.webm.md5
+086c7edcffd699ae7d99d710fd7e53b18910ca5b *vp90-2-08-tile_1x2_frame_parallel.webm
+e981ecaabb29a80e0cbc1f4002384965ce8e95bb *vp90-2-08-tile_1x2_frame_parallel.webm.md5
+ed79be026a6f28646c5825da1c12d1fbc70f96a4 *vp90-2-08-tile_1x2.webm
+45b404e025841c9750895fc1a9f6bd384fe6a315 *vp90-2-08-tile_1x2.webm.md5
+cf8ea970c776797aae71dac8317ea926d9431cab *vp90-2-08-tile_1x4_frame_parallel.webm
+a481fbea465010b57af5a19ebf6d4a5cfe5b9278 *vp90-2-08-tile_1x4_frame_parallel.webm.md5
+0203ec456277a01aec401e7fb6c72c9a7e5e3f9d *vp90-2-08-tile_1x4.webm
+c9b237dfcc01c1b414fbcaa481d014a906ef7998 *vp90-2-08-tile_1x4.webm.md5
+20c75157e91ab41f82f70ffa73d5d01df8469287 *vp90-2-08-tile-4x4.webm
+ae7451810247fd13975cc257aa0301ff17102255 *vp90-2-08-tile-4x4.webm.md5
+2ec6e15422ac7a61af072dc5f27fcaf1942ce116 *vp90-2-08-tile-4x1.webm
+0094f5ee5e46345017c30e0aa4835b550212d853 *vp90-2-08-tile-4x1.webm.md5
+edea45dac4a3c2e5372339f8851d24c9bef803d6 *vp90-2-09-subpixel-00.ivf
+5428efc4bf92191faedf4a727fcd1d94966a7abc *vp90-2-09-subpixel-00.ivf.md5
+8cdd435d89029987ee196896e21520e5f879f04d *vp90-2-bbb_1280x720_tile_1x4_1310kbps.webm
+091b373aa2ecb59aa5c647affd5bcafcc7547364 *vp90-2-bbb_1920x1080_tile_1x1_2581kbps.webm
+87ee28032b0963a44b73a850fcc816a6dc83efbb *vp90-2-bbb_1920x1080_tile_1x4_2586kbps.webm
+c6ce25c4bfd4bdfc2932b70428e3dfe11210ec4f *vp90-2-bbb_1920x1080_tile_1x4_fpm_2304kbps.webm
+2064bdb22aa71c2691e0469fb62e8087a43f08f8 *vp90-2-bbb_426x240_tile_1x1_180kbps.webm
+8080eda22694910162f0996e8a962612f381a57f *vp90-2-bbb_640x360_tile_1x2_337kbps.webm
+a484b335c27ea189c0f0d77babea4a510ce12d50 *vp90-2-bbb_854x480_tile_1x2_651kbps.webm
+3eacf1f006250be4cc5c92a7ef146e385ee62653 *vp90-2-sintel_1280x546_tile_1x4_1257kbps.webm
+217f089a16447490823127b36ce0d945522accfd *vp90-2-sintel_1920x818_tile_1x4_fpm_2279kbps.webm
+eedb3c641e60dacbe082491a16df529a5c9187df *vp90-2-sintel_426x182_tile_1x1_171kbps.webm
+cb7e4955af183dff33bcba0c837f0922ab066400 *vp90-2-sintel_640x272_tile_1x2_318kbps.webm
+48613f9380e2580002f8a09d6e412ea4e89a52b9 *vp90-2-sintel_854x364_tile_1x2_621kbps.webm
+990a91f24dd284562d21d714ae773dff5452cad8 *vp90-2-tos_1280x534_tile_1x4_1306kbps.webm
+aa402217577a659cfc670157735b4b8e9aa670fe *vp90-2-tos_1280x534_tile_1x4_fpm_952kbps.webm
+b6dd558c90bca466b4bcbd03b3371648186465a7 *vp90-2-tos_1920x800_tile_1x4_fpm_2335kbps.webm
+1a9c2914ba932a38f0a143efc1ad0e318e78888b *vp90-2-tos_426x178_tile_1x1_181kbps.webm
+a3d2b09f24debad4747a1b3066f572be4273bced *vp90-2-tos_640x266_tile_1x2_336kbps.webm
+c64b03b5c090e6888cb39685c31f00a6b79fa45c *vp90-2-tos_854x356_tile_1x2_656kbps.webm
+94b533dbcf94292001e27cc51fec87f9e8c90c0b *vp90-2-tos_854x356_tile_1x2_fpm_546kbps.webm
+0e7cd4135b231c9cea8d76c19f9e84b6fd77acec *vp90-2-08-tile_1x8_frame_parallel.webm
+c9b6850af28579b031791066457f4cb40df6e1c7 *vp90-2-08-tile_1x8_frame_parallel.webm.md5
+e448b6e83490bca0f8d58b4f4b1126a17baf4b0c *vp90-2-08-tile_1x8.webm
+5e524165f0397e6141d914f4f0a66267d7658376 *vp90-2-08-tile_1x8.webm.md5
+a34e14923d6d17b1144254d8187d7f85b700a63c *vp90-2-02-size-lf-1920x1080.webm
+e3b28ddcfaeb37fb4d132b93f92642a9ad17c22d *vp90-2-02-size-lf-1920x1080.webm.md5
+d48c5db1b0f8e60521a7c749696b8067886033a3 *vp90-2-09-aq2.webm
+84c1599298aac78f2fc05ae2274575d10569dfa0 *vp90-2-09-aq2.webm.md5
+55fc55ed73d578ed60fad05692579873f8bad758 *vp90-2-09-lf_deltas.webm
+54638c38009198c38c8f3b25c182b709b6c1fd2e *vp90-2-09-lf_deltas.webm.md5
+510d95f3beb3b51c572611fdaeeece12277dac30 *vp90-2-10-show-existing-frame.webm
+14d631096f4bfa2d71f7f739aec1448fb3c33bad *vp90-2-10-show-existing-frame.webm.md5
+d2feea7728e8d2c615981d0f47427a4a5a45d881 *vp90-2-10-show-existing-frame2.webm
+5f7c7811baa3e4f03be1dd78c33971b727846821 *vp90-2-10-show-existing-frame2.webm.md5
+b4318e75f73a6a08992c7326de2fb589c2a794c7 *vp90-2-11-size-351x287.webm
+b3c48382cf7d0454e83a02497c229d27720f9e20 *vp90-2-11-size-351x287.webm.md5
+8e0096475ea2535bac71d3e2fc09e0c451c444df *vp90-2-11-size-351x288.webm
+19e003804ec1dfc5464813b32339a15d5ba7b42f *vp90-2-11-size-351x288.webm.md5
+40cd1d6a188d7a88b21ebac1e573d3f270ab261e *vp90-2-11-size-352x287.webm
+68f515abe3858fc1eded46c8e6b2f727d43b5331 *vp90-2-11-size-352x287.webm.md5
+9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_1.ivf
+952eaac6eefa6f62179ed1db3e922fd42fecc624 *vp90-2-12-droppable_1.ivf.md5
+9a510769ff23db410880ec3029d433e87d17f7fc *vp90-2-12-droppable_2.ivf
+92a756469fa438220524e7fa6ac1d38c89514d17 *vp90-2-12-droppable_2.ivf.md5
+c21e97e4ba486520118d78b01a5cb6e6dc33e190 *vp90-2-12-droppable_3.ivf
+601abc9e4176c70f82ac0381365e9b151fdd24cd *vp90-2-12-droppable_3.ivf.md5
+61c640dad23cd4f7ad811b867e7b7e3521f4e3ba *vp90-2-13-largescaling.webm
+bca1b02eebdb088fa3f389fe0e7571e75a71f523 *vp90-2-13-largescaling.webm.md5
+c740708fa390806eebaf669909c1285ab464f886 *vp90-2-14-resize-fp-tiles-1-2.webm
+c7b85ffd8e11500f73f52e7dc5a47f57c393d47f *vp90-2-14-resize-fp-tiles-1-2.webm.md5
+ec8faa352a08f7033c60f29f80d505e2d7daa103 *vp90-2-14-resize-fp-tiles-1-4.webm
+6852c783fb421bda5ded3d4c5a3ffc46de03fbc1 *vp90-2-14-resize-fp-tiles-1-4.webm.md5
+8af61853ac0d07c4cb5bf7c2016661ba350b3497 *vp90-2-14-resize-fp-tiles-1-8.webm
+571353bac89fea60b5706073409aa3c0d42aefe9 *vp90-2-14-resize-fp-tiles-1-8.webm.md5
+b1c187ed69931496b82ec194017a79831bafceef *vp90-2-14-resize-fp-tiles-1-16.webm
+1c199a41afe42ce303944d70089eaaa2263b4a09 *vp90-2-14-resize-fp-tiles-1-16.webm.md5
+8eaae5a6f2dff934610b0c7a917d7f583ba74aa5 *vp90-2-14-resize-fp-tiles-2-1.webm
+db18fcf915f7ffaea6c39feab8bda6c1688af011 *vp90-2-14-resize-fp-tiles-2-1.webm.md5
+bc3046d138941e2a20e9ceec0ff6d25c25d12af3 *vp90-2-14-resize-fp-tiles-4-1.webm
+393211b808030d09a79927b17a4374b2f68a60ae *vp90-2-14-resize-fp-tiles-4-1.webm.md5
+6e8f8e31721a0f7f68a2964e36e0e698c2e276b1 *vp90-2-14-resize-fp-tiles-8-1.webm
+491fd3cd78fb0577bfe905bb64bbf64bd7d29140 *vp90-2-14-resize-fp-tiles-8-1.webm.md5
+cc5958da2a7edf739cd2cfeb18bd05e77903087e *vp90-2-14-resize-fp-tiles-16-1.webm
+0b58daf55aaf9063bf5b4fb33393d18b417dc428 *vp90-2-14-resize-fp-tiles-16-1.webm.md5
+821eeecc9d8c6a316134dd42d1ff057787d8047b *vp90-2-14-resize-fp-tiles-2-4.webm
+374c549f2839a3d0b732c4e3650700144037e76c *vp90-2-14-resize-fp-tiles-2-4.webm.md5
+dff8c8e49aacea9f4c7f22cb882da984e2a1b405 *vp90-2-14-resize-fp-tiles-2-8.webm
+e5b8820a7c823b21297d6e889e57ec401882c210 *vp90-2-14-resize-fp-tiles-2-8.webm.md5
+77629e4b23e32896aadf6e994c78bd4ffa1c7797 *vp90-2-14-resize-fp-tiles-2-16.webm
+1937f5df032664ac345d4613ad4417b4967b1230 *vp90-2-14-resize-fp-tiles-2-16.webm.md5
+380ba5702bb1ec7947697314ab0300b5c56a1665 *vp90-2-14-resize-fp-tiles-4-2.webm
+fde7b30d2aa64c1e851a4852f655d79fc542cf66 *vp90-2-14-resize-fp-tiles-4-2.webm.md5
+dc784b258ffa2abc2ae693d11792acf0bb9cb74f *vp90-2-14-resize-fp-tiles-8-2.webm
+edf26f0130aeee8342d49c2c8f0793ad008782d9 *vp90-2-14-resize-fp-tiles-8-2.webm.md5
+8e575789fd63ebf69e8eff1b9a4351a249a73bee *vp90-2-14-resize-fp-tiles-16-2.webm
+b6415318c1c589a1f64b9d569ce3cabbec2e0d52 *vp90-2-14-resize-fp-tiles-16-2.webm.md5
+e3adc944a11c4c5517e63664c84ebb0847b64d81 *vp90-2-14-resize-fp-tiles-4-8.webm
+03cba0532bc90a05b1990db830bf5701e24e7982 *vp90-2-14-resize-fp-tiles-4-8.webm.md5
+3b27a991eb6d78dce38efab35b7db682e8cbbee3 *vp90-2-14-resize-fp-tiles-4-16.webm
+5d16b7f82bf59f802724ddfd97abb487150b1c9d *vp90-2-14-resize-fp-tiles-4-16.webm.md5
+d5fed8c28c1d4c7e232ebbd25cf758757313ed96 *vp90-2-14-resize-fp-tiles-8-4.webm
+5a8ff8a52cbbde7bfab569beb6d971c5f8b904f7 *vp90-2-14-resize-fp-tiles-8-4.webm.md5
+17a5faa023d77ee9dad423a4e0d3145796bbc500 *vp90-2-14-resize-fp-tiles-16-4.webm
+2ef8daa3c3e750fd745130d0a76a39fe86f0448f *vp90-2-14-resize-fp-tiles-16-4.webm.md5
+9361e031f5cc990d8740863e310abb5167ae351e *vp90-2-14-resize-fp-tiles-8-16.webm
+57f13a2197486584f4e1a4f82ad969f3abc5a1a2 *vp90-2-14-resize-fp-tiles-8-16.webm.md5
+5803fc6fcbfb47b7661f3fcc6499158a32b56675 *vp90-2-14-resize-fp-tiles-16-8.webm
+be0fe64a1a4933696ff92d93f9bdecdbd886dc13 *vp90-2-14-resize-fp-tiles-16-8.webm.md5
+0ac0f6d20a0afed77f742a3b9acb59fd7b9cb093 *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm
+1765315acccfe6cd12230e731369fcb15325ebfa *vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm.md5
+4a2b7a683576fe8e330c7d1c4f098ff4e70a43a8 *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm
+1ef480392112b3509cb190afbb96f9a38dd9fbac *vp90-2-14-resize-fp-tiles-16-8-4-2-1.webm.md5
+e615575ded499ea1d992f3b38e3baa434509cdcd *vp90-2-15-segkey.webm
+e3ab35d4316c5e81325c50f5236ceca4bc0d35df *vp90-2-15-segkey.webm.md5
+9b7ca2cac09d34c4a5d296c1900f93b1e2f69d0d *vp90-2-15-segkey_adpq.webm
+8f46ba5f785d0c2170591a153e0d0d146a7c8090 *vp90-2-15-segkey_adpq.webm.md5
+698a6910a97486b833073ef0c0b18d75dce57ee8 *vp90-2-16-intra-only.webm
+5661b0168752969f055eec37b05fa9fa947dc7eb *vp90-2-16-intra-only.webm.md5
+c01bb7938f9a9f25e0c37afdec2f2fb73b6cc7fa *vp90-2-17-show-existing-frame.webm
+cc75f351818b9a619818f5cc77b9bc013d0c1e11 *vp90-2-17-show-existing-frame.webm.md5
+013708bd043f0821a3e56fb8404d82e7a0c7af6c *vp91-2-04-yuv422.webm
+1e58a7d23adad830a672f1733c9d2ae17890d59c *vp91-2-04-yuv422.webm.md5
+25d78f28948789d159a9453ebc13048b818251b1 *vp91-2-04-yuv440.webm
+81b3870b27a7f695ef6a43e87ab04bbdb5aee2f5 *vp91-2-04-yuv440.webm.md5
+0321d507ce62dedc8a51b4e9011f7a19aed9c3dc *vp91-2-04-yuv444.webm
+367e423dd41fdb49aa028574a2cfec5c2f325c5c *vp91-2-04-yuv444.webm.md5
+f77673b566f686853adefe0c578ad251b7241281 *vp92-2-20-10bit-yuv420.webm
+abdedfaddacbbe1a15ac7a54e86360f03629fb7a *vp92-2-20-10bit-yuv420.webm.md5
+0c2c355a1b17b28537c5a3b19997c8783b69f1af *vp92-2-20-12bit-yuv420.webm
+afb2c2798703e039189b0a15c8ac5685aa51d33f *vp92-2-20-12bit-yuv420.webm.md5
+0d661bc6e83da33238981481efd1b1802d323d88 *vp93-2-20-10bit-yuv422.webm
+10318907063db22eb02fad332556edbbecd443cc *vp93-2-20-10bit-yuv422.webm.md5
+ebc6be2f7511a0bdeac0b18c67f84ba7168839c7 *vp93-2-20-12bit-yuv422.webm
+235232267c6a1dc8a11e45d600f1c99d2f8b42d4 *vp93-2-20-12bit-yuv422.webm.md5
+f76b11b26d4beaceac7a7e7729dd5054d095164f *vp93-2-20-10bit-yuv440.webm
+757b33b5ac969c5999999488a731a3d1e6d9fb88 *vp93-2-20-10bit-yuv440.webm.md5
+df8807dbd29bec795c2db9c3c18e511fbb988101 *vp93-2-20-12bit-yuv440.webm
+ea4100930c3f59a1c23fbb33ab0ea01151cae159 *vp93-2-20-12bit-yuv440.webm.md5
+189c1b5f404ff41a50a7fc96341085ad541314a9 *vp93-2-20-10bit-yuv444.webm
+2dd0177c2f9d970b6e698892634c653630f91f40 *vp93-2-20-10bit-yuv444.webm.md5
+bd44cf6e1c27343e3639df9ac21346aedd5d6973 *vp93-2-20-12bit-yuv444.webm
+f36e5bdf5ec3213f32c0ddc82f95d82c5133bf27 *vp93-2-20-12bit-yuv444.webm.md5
+eb438c6540eb429f74404eedfa3228d409c57874 *desktop_640_360_30.yuv
+89e70ebd22c27d275fe14dc2f1a41841a6d8b9ab *kirland_640_480_30.yuv
+33c533192759e5bb4f07abfbac389dc259db4686 *macmarcomoving_640_480_30.yuv
+8bfaab121080821b8f03b23467911e59ec59b8fe *macmarcostationary_640_480_30.yuv
+70894878d916a599842d9ad0dcd24e10c13e5467 *niklas_640_480_30.yuv
+8784b6df2d8cc946195a90ac00540500d2e522e4 *tacomanarrows_640_480_30.yuv
+edd86a1f5e62fd9da9a9d46078247759c2638009 *tacomasmallcameramovement_640_480_30.yuv
+9a70e8b7d14fba9234d0e51dce876635413ce444 *thaloundeskmtg_640_480_30.yuv
+e7d315dbf4f3928779e0dc624311196d44491d32 *niklas_1280_720_30.yuv
+c77e4a26616add298a05dd5d12397be22c0e40c5 *vp90-2-18-resize.ivf
+c12918cf0a716417fba2de35c3fc5ab90e52dfce *vp90-2-18-resize.ivf.md5
+717da707afcaa1f692ff1946f291054eb75a4f06 *screendata.y4m
+b7c1296630cdf1a7ef493d15ff4f9eb2999202f6 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-08-tile_1x2_frame_parallel.webm.ivf.s47039_r01-05_b6-.ivf.res
+359e138dfb66863828397b77000ea7a83c844d02 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf
+bbd33de01c17b165b4ce00308e8a19a942023ab8 *invalid-vp90-2-08-tile_1x8_frame_parallel.webm.ivf.s288_r01-05_b6-.ivf.res
+fac89b5735be8a86b0dc05159f996a5c3208ae32 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-09-aq2.webm.ivf.s3984_r01-05_b6-.v2.ivf.res
+4506dfdcdf8ee4250924b075a0dcf1f070f72e5a *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf
+bcdedaf168ac225575468fda77502d2dc9fd5baa *invalid-vp90-2-09-subpixel-00.ivf.s19552_r01-05_b6-.v2.ivf.res
+65e93f9653bcf65b022f7d225268d1a90a76e7bb *vp90-2-19-skip.webm
+368dccdde5288c13c25695d2eacdc7402cadf613 *vp90-2-19-skip.webm.md5
+ffe460282df2b0e7d4603c2158653ad96f574b02 *vp90-2-19-skip-01.webm
+bd21bc9eda4a4a36b221d71ede3a139fc3c7bd85 *vp90-2-19-skip-01.webm.md5
+178f5bd239e38cc1cc2657a7a5e1a9f52ad2d3fe *vp90-2-19-skip-02.webm
+9020d5e260bd7df08e2b3d4b86f8623cee3daea2 *vp90-2-19-skip-02.webm.md5
+b03c408cf23158638da18dbc3323b99a1635c68a *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf
+0a3884edb3fd8f9d9b500223e650f7de257b67d8 *invalid-vp90-2-12-droppable_1.ivf.s3676_r01-05_b6-.ivf.res
+5e67e24e7f53fd189e565513cef8519b1bd6c712 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf
+741158f67c0d9d23726624d06bdc482ad368afc9 *invalid-vp90-2-05-resize.ivf.s59293_r01-05_b6-.ivf.res
+8b1f7bf7e86c0976d277f60e8fcd9539e75a079a *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf
+9c6bdf048fb2e66f07d4b4db5b32e6f303bd6109 *invalid-vp90-2-09-subpixel-00.ivf.s20492_r01-05_b6-.v2.ivf.res
+552e372e9b78127389fb06b34545df2cec15ba6d *invalid-vp91-2-mixedrefcsp-444to420.ivf
+a61774cf03fc584bd9f0904fc145253bb8ea6c4c *invalid-vp91-2-mixedrefcsp-444to420.ivf.res
+812d05a64a0d83c1b504d0519927ddc5a2cdb273 *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf
+1e472baaf5f6113459f0399a38a5a5e68d17799d *invalid-vp90-2-12-droppable_1.ivf.s73804_r01-05_b6-.ivf.res
+f97088c7359fc8d3d5aa5eafe57bc7308b3ee124 *vp90-2-20-big_superframe-01.webm
+47d7d409785afa33b123376de0c907336e6c7bd7 *vp90-2-20-big_superframe-01.webm.md5
+65ade6d2786209582c50d34cfe22b3cdb033abaf *vp90-2-20-big_superframe-02.webm
+7c0ed8d04c4d06c5411dd2e5de2411d37f092db5 *vp90-2-20-big_superframe-02.webm.md5
+667ec8718c982aef6be07eb94f083c2efb9d2d16 *vp90-2-07-frame_parallel-1.webm
+bfc82bf848e9c05020d61e3ffc1e62f25df81d19 *vp90-2-07-frame_parallel-1.webm.md5
+efd5a51d175cfdacd169ed23477729dc558030dc *invalid-vp90-2-07-frame_parallel-1.webm
+9f912712ec418be69adb910e2ca886a63c4cec08 *invalid-vp90-2-07-frame_parallel-2.webm
+445f5a53ca9555341852997ccdd480a51540bd14 *invalid-vp90-2-07-frame_parallel-3.webm
+d18c90709a0d03c82beadf10898b27d88fff719c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf
+d06285d109ecbaef63b0cbcc44d70a129186f51c *invalid-vp90-2-03-size-224x196.webm.ivf.s44156_r01-05_b6-.ivf.res
+e60d859b0ef2b331b21740cf6cb83fabe469b079 *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf
+0ae808dca4d3c1152a9576e14830b6faa39f1b4a *invalid-vp90-2-03-size-202x210.webm.ivf.s113306_r01-05_b6-.ivf.res
+9cfc855459e7549fd015c79e8eca512b2f2cb7e3 *niklas_1280_720_30.y4m
+5b5763b388b1b52a81bb82b39f7ec25c4bd3d0e1 *desktop_credits.y4m
+85771f6ab44e4a0226e206c0cde8351dd5918953 *vp90-2-02-size-130x132.webm
+512dad5eabbed37b4bbbc64ce153f1a5484427b8 *vp90-2-02-size-130x132.webm.md5
+01f7127d40360289db63b27f61cb9afcda350e95 *vp90-2-02-size-132x130.webm
+4a94275328ae076cf60f966c097a8721010fbf5a *vp90-2-02-size-132x130.webm.md5
+f41c0400b5716b4b70552c40dd03d44be131e1cc *vp90-2-02-size-132x132.webm
+1a69e989f697e424bfe3e3e8a77bb0c0992c8e47 *vp90-2-02-size-132x132.webm.md5
+94a5cbfacacba100e0c5f7861c72a1b417feca0f *vp90-2-02-size-178x180.webm
+dedfecf1d784bcf70629592fa5e6f01d5441ccc9 *vp90-2-02-size-178x180.webm.md5
+4828b62478c04014bba3095a83106911a71cf387 *vp90-2-02-size-180x178.webm
+423da2b861050c969d78ed8e8f8f14045d1d8199 *vp90-2-02-size-180x178.webm.md5
+338f7c9282f43e29940f5391118aadd17e4f9234 *vp90-2-02-size-180x180.webm
+6c2ef013392310778dca5dd5351160eca66b0a60 *vp90-2-02-size-180x180.webm.md5
+679fa7d6807e936ff937d7b282e7dbd8ac76447e *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm
+fc7267ab8fc2bf5d6c234e34ee6c078a967b4888 *vp90-2-14-resize-10frames-fp-tiles-1-2-4-8.webm.md5
+9d33a137c819792209c5ce4e4e1ee5da73d574fe *vp90-2-14-resize-10frames-fp-tiles-1-2.webm
+0c78a154956a8605d050bdd75e0dcc4d39c040a6 *vp90-2-14-resize-10frames-fp-tiles-1-2.webm.md5
+d6a8d8c57f66a91d23e8e7df480f9ae841e56c37 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm
+e9b4e8c7b33b5fda745d340c3f47e6623ae40cf2 *vp90-2-14-resize-10frames-fp-tiles-1-4.webm.md5
+aa6fe043a0c4a42b49c87ebbe812d4afd9945bec *vp90-2-14-resize-10frames-fp-tiles-1-8.webm
+028520578994c2d013d4c0129033d4f2ff31bbe0 *vp90-2-14-resize-10frames-fp-tiles-1-8.webm.md5
+d1d5463c9ea7b5cc5f609ddedccddf656f348d1a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm
+92d5872f5bdffbed721703b7e959b4f885e3d77a *vp90-2-14-resize-10frames-fp-tiles-2-1.webm.md5
+677cb29de1215d97346015af5807a9b1faad54cf *vp90-2-14-resize-10frames-fp-tiles-2-4.webm
+a5db19f977094ec3fd60b4f7671b3e6740225e12 *vp90-2-14-resize-10frames-fp-tiles-2-4.webm.md5
+cdd3c52ba21067efdbb2de917fe2a965bf27332e *vp90-2-14-resize-10frames-fp-tiles-2-8.webm
+db17ec5d894ea8b8d0b7f32206d0dd3d46dcfa6d *vp90-2-14-resize-10frames-fp-tiles-2-8.webm.md5
+0f6093c472125d05b764d7d1965c1d56771c0ea2 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm
+bc7c79e1bee07926dd970462ce6f64fc30eec3e1 *vp90-2-14-resize-10frames-fp-tiles-4-1.webm.md5
+c5142e2bff4091338196c8ea8bc9266e64f548bc *vp90-2-14-resize-10frames-fp-tiles-4-2.webm
+22aa3dd430b69fd3d92f6561bac86deeed90486d *vp90-2-14-resize-10frames-fp-tiles-4-2.webm.md5
+ede8b1466d2f26e1b1bd9602addb9cd1017e1d8c *vp90-2-14-resize-10frames-fp-tiles-4-8.webm
+508d5ebb9c0eac2a4100281a3ee052ec2fc19217 *vp90-2-14-resize-10frames-fp-tiles-4-8.webm.md5
+2b292e3392854cd1d76ae597a6f53656cf741cfa *vp90-2-14-resize-10frames-fp-tiles-8-1.webm
+1c24e54fa19e94e1722f24676404444e941c3d31 *vp90-2-14-resize-10frames-fp-tiles-8-1.webm.md5
+61beda21064e09634564caa6697ab90bd53c9af7 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm
+9c0657b4d9e1d0e4c9d28a90e5a8630a65519124 *vp90-2-14-resize-10frames-fp-tiles-8-2.webm.md5
+1758c50a11a7c92522749b4a251664705f1f0d4b *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm
+4f454a06750614314ae15a44087b79016fe2db97 *vp90-2-14-resize-10frames-fp-tiles-8-4-2-1.webm.md5
+3920c95ba94f1f048a731d9d9b416043b44aa4bd *vp90-2-14-resize-10frames-fp-tiles-8-4.webm
+4eb347a0456d2c49a1e1d8de5aa1c51acc39887e *vp90-2-14-resize-10frames-fp-tiles-8-4.webm.md5
+4b95a74c032a473b6683d7ad5754db1b0ec378e9 *vp90-2-21-resize_inter_1280x720_5_1-2.webm
+a7826dd386bedfe69d02736969bfb47fb6a40a5e *vp90-2-21-resize_inter_1280x720_5_1-2.webm.md5
+5cfff79e82c4d69964ccb8e75b4f0c53b9295167 *vp90-2-21-resize_inter_1280x720_5_3-4.webm
+a18f57db4a25e1f543a99f2ceb182e00db0ee22f *vp90-2-21-resize_inter_1280x720_5_3-4.webm.md5
+d26db0811bf30eb4131d928669713e2485f8e833 *vp90-2-21-resize_inter_1280x720_7_1-2.webm
+fd6f9f332cd5bea4c0f0d57be4297bea493cc5a1 *vp90-2-21-resize_inter_1280x720_7_1-2.webm.md5
+5c7d73d4d268e2ba9593b31cb091fd339505c7fd *vp90-2-21-resize_inter_1280x720_7_3-4.webm
+7bbb949cabc1e70dadcc74582739f63b833034e0 *vp90-2-21-resize_inter_1280x720_7_3-4.webm.md5
+f2d2a41a60eb894aff0c5854afca15931f1445a8 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm
+66d7789992613ac9d678ff905ff1059daa1b89e4 *vp90-2-21-resize_inter_1920x1080_5_1-2.webm.md5
+764edb75fe7dd64e73a1b4f3b4b2b1bf237a4dea *vp90-2-21-resize_inter_1920x1080_5_3-4.webm
+f78bea1075983fd990e7f25d4f31438f9b5efa34 *vp90-2-21-resize_inter_1920x1080_5_3-4.webm.md5
+96496f2ade764a5de9f0c27917c7df1f120fb2ef *vp90-2-21-resize_inter_1920x1080_7_1-2.webm
+2632b635135ed5ecd67fd22dec7990d29c4f4cb5 *vp90-2-21-resize_inter_1920x1080_7_1-2.webm.md5
+74889ea42001bf41428cb742ca74e65129c886dc *vp90-2-21-resize_inter_1920x1080_7_3-4.webm
+d2cf3b25956415bb579d368e7098097e482dd73a *vp90-2-21-resize_inter_1920x1080_7_3-4.webm.md5
+4658986a8ce36ebfcc80a1903e446eaab3985336 *vp90-2-21-resize_inter_320x180_5_1-2.webm
+8a3d8cf325109ffa913cc9426c32eea8c202a09a *vp90-2-21-resize_inter_320x180_5_1-2.webm.md5
+16303aa45176520ee42c2c425247aadc1506b881 *vp90-2-21-resize_inter_320x180_5_3-4.webm
+41cab1ddf7715b680a4dbce42faa9bcd72af4e5c *vp90-2-21-resize_inter_320x180_5_3-4.webm.md5
+56648adcee66dd0e5cb6ac947f5ee1b9cc8ba129 *vp90-2-21-resize_inter_320x180_7_1-2.webm
+70047377787003cc03dda7b2394e6d7eaa666d9e *vp90-2-21-resize_inter_320x180_7_1-2.webm.md5
+d2ff99165488499cc55f75929f1ce5ca9c9e359b *vp90-2-21-resize_inter_320x180_7_3-4.webm
+e69019e378114a4643db283b66d1a7e304761a56 *vp90-2-21-resize_inter_320x180_7_3-4.webm.md5
+4834d129bed0f4289d3a88f2ae3a1736f77621b0 *vp90-2-21-resize_inter_320x240_5_1-2.webm
+a75653c53d22b623c1927fc0088da21dafef21f4 *vp90-2-21-resize_inter_320x240_5_1-2.webm.md5
+19818e1b7fd1c1e63d8873c31b0babe29dd33ba6 *vp90-2-21-resize_inter_320x240_5_3-4.webm
+8d89814ff469a186312111651b16601dfbce4336 *vp90-2-21-resize_inter_320x240_5_3-4.webm.md5
+ac8057bae52498f324ce92a074d5f8207cc4a4a7 *vp90-2-21-resize_inter_320x240_7_1-2.webm
+2643440898c83c08cc47bc744245af696b877c24 *vp90-2-21-resize_inter_320x240_7_1-2.webm.md5
+cf4a4cd38ac8b18c42d8c25a3daafdb39132256b *vp90-2-21-resize_inter_320x240_7_3-4.webm
+70ba8ec9120b26e9b0ffa2c79b432f16cbcb50ec *vp90-2-21-resize_inter_320x240_7_3-4.webm.md5
+669f10409fe1c4a054010162ca47773ea1fdbead *vp90-2-21-resize_inter_640x360_5_1-2.webm
+6355a04249004a35fb386dd1024214234f044383 *vp90-2-21-resize_inter_640x360_5_1-2.webm.md5
+c23763b950b8247c1775d1f8158d93716197676c *vp90-2-21-resize_inter_640x360_5_3-4.webm
+59e6fc381e3ec3b7bdaac586334e0bc944d18fb6 *vp90-2-21-resize_inter_640x360_5_3-4.webm.md5
+71b45cbfdd068baa1f679a69e5e6f421d256a85f *vp90-2-21-resize_inter_640x360_7_1-2.webm
+1416fc761b690c54a955c4cf017fa078520e8c18 *vp90-2-21-resize_inter_640x360_7_1-2.webm.md5
+6c409903279448a697e4db63bab1061784bcd8d2 *vp90-2-21-resize_inter_640x360_7_3-4.webm
+60de1299793433a630b71130cf76c9f5965758e2 *vp90-2-21-resize_inter_640x360_7_3-4.webm.md5
+852b597b8af096d90c80bf0ed6ed3b336b851f19 *vp90-2-21-resize_inter_640x480_5_1-2.webm
+f6856f19236ee46ed462bd0a2e7e72b9c3b9cea6 *vp90-2-21-resize_inter_640x480_5_1-2.webm.md5
+792a16c6f60043bd8dceb515f0b95b8891647858 *vp90-2-21-resize_inter_640x480_5_3-4.webm
+68ffe59877e9a7863805e1c0a3ce18ce037d7c9d *vp90-2-21-resize_inter_640x480_5_3-4.webm.md5
+61e044c4759972a35ea3db8c1478a988910a4ef4 *vp90-2-21-resize_inter_640x480_7_1-2.webm
+7739bfca167b1b43fea72f807f01e097b7cb98d8 *vp90-2-21-resize_inter_640x480_7_1-2.webm.md5
+7291af354b4418917eee00e3a7e366086a0b7a10 *vp90-2-21-resize_inter_640x480_7_3-4.webm
+4a18b09ccb36564193f0215f599d745d95bb558c *vp90-2-21-resize_inter_640x480_7_3-4.webm.md5
diff --git a/src/third_party/libvpx/test/test.mk b/src/third_party/libvpx/test/test.mk
new file mode 100644
index 0000000..04acd96
--- /dev/null
+++ b/src/third_party/libvpx/test/test.mk
@@ -0,0 +1,190 @@
+LIBVPX_TEST_SRCS-yes += acm_random.h
+LIBVPX_TEST_SRCS-yes += clear_system_state.h
+LIBVPX_TEST_SRCS-yes += codec_factory.h
+LIBVPX_TEST_SRCS-yes += md5_helper.h
+LIBVPX_TEST_SRCS-yes += register_state_check.h
+LIBVPX_TEST_SRCS-yes += test.mk
+LIBVPX_TEST_SRCS-yes += test_libvpx.cc
+LIBVPX_TEST_SRCS-yes += test_vectors.cc
+LIBVPX_TEST_SRCS-yes += test_vectors.h
+LIBVPX_TEST_SRCS-yes += util.h
+LIBVPX_TEST_SRCS-yes += video_source.h
+
+##
+## BLACK BOX TESTS
+##
+## Black box tests only use the public API.
+##
+LIBVPX_TEST_SRCS-yes                   += ../md5_utils.h ../md5_utils.c
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ivf_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += ../y4minput.h ../y4minput.c
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += altref_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += aq_segment_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += datarate_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += encode_api_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += error_resilience_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += i420_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += realtime_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += resize_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += y4m_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += yuv_video_source.h
+
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += config_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += cq_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += keyframe_test.cc
+
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += byte_alignment_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += external_frame_buffer_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += invalid_file_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += user_priv_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_frame_parallel_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_refresh_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += active_map_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += borders_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += cpu_speed_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += frame_size_tests.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_lossless_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_end_to_end_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_ethread_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += level_test.cc
+
+LIBVPX_TEST_SRCS-yes                   += decode_test_driver.cc
+LIBVPX_TEST_SRCS-yes                   += decode_test_driver.h
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += encode_test_driver.cc
+LIBVPX_TEST_SRCS-yes                   += encode_test_driver.h
+
+## IVF writing.
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += ../ivfenc.c ../ivfenc.h
+
+## Y4m parsing.
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS)    += y4m_test.cc ../y4menc.c ../y4menc.h
+
+## WebM Parsing
+ifeq ($(CONFIG_WEBM_IO), yes)
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.cc
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.cc
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvparser.h
+LIBWEBM_PARSER_SRCS += ../third_party/libwebm/mkvparser/mkvreader.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += $(LIBWEBM_PARSER_SRCS)
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ../tools_common.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ../webmdec.cc
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += ../webmdec.h
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += webm_video_source.h
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_skip_loopfilter_test.cc
+endif
+
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += decode_api_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_DECODERS)    += test_vector_test.cc
+
+# Currently we only support decoder perf tests for vp9. Also they read from WebM
+# files, so WebM IO is required.
+ifeq ($(CONFIG_DECODE_PERF_TESTS)$(CONFIG_VP9_DECODER)$(CONFIG_WEBM_IO), \
+      yesyesyes)
+LIBVPX_TEST_SRCS-yes                   += decode_perf_test.cc
+endif
+
+# encode perf tests are vp9 only
+ifeq ($(CONFIG_ENCODE_PERF_TESTS)$(CONFIG_VP9_ENCODER), yesyes)
+LIBVPX_TEST_SRCS-yes += encode_perf_test.cc
+endif
+
+##
+## WHITE BOX TESTS
+##
+## Whitebox tests invoke functions not exposed via the public API. Certain
+## shared library builds don't make these functions accessible.
+##
+ifeq ($(CONFIG_SHARED),)
+
+## VP8
+ifeq ($(CONFIG_VP8),yes)
+
+# These tests require both the encoder and decoder to be built.
+ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_VP8_DECODER),yesyes)
+LIBVPX_TEST_SRCS-yes                   += vp8_boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes                   += vp8_fragments_test.cc
+endif
+
+LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC)    += add_noise_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_POSTPROC)    += pp_filter_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_DECODER) += vp8_decrypt_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += quantize_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += set_roi.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += variance_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP8_ENCODER) += vp8_fdct4x4_test.cc
+
+LIBVPX_TEST_SRCS-yes                   += idct_test.cc
+LIBVPX_TEST_SRCS-yes                   += sixtap_predict_test.cc
+LIBVPX_TEST_SRCS-yes                   += vpx_scale_test.cc
+
+ifeq ($(CONFIG_VP8_ENCODER)$(CONFIG_TEMPORAL_DENOISING),yesyes)
+LIBVPX_TEST_SRCS-$(HAVE_SSE2) += vp8_denoiser_sse2_test.cc
+endif
+
+endif # VP8
+
+## VP9
+ifeq ($(CONFIG_VP9),yes)
+
+# These tests require both the encoder and decoder to be built.
+ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_DECODER),yesyes)
+# IDCT test currently depends on FDCT function
+LIBVPX_TEST_SRCS-yes                   += idct8x8_test.cc
+LIBVPX_TEST_SRCS-yes                   += partial_idct_test.cc
+LIBVPX_TEST_SRCS-yes                   += superframe_test.cc
+LIBVPX_TEST_SRCS-yes                   += tile_independence_test.cc
+LIBVPX_TEST_SRCS-yes                   += vp9_boolcoder_test.cc
+LIBVPX_TEST_SRCS-yes                   += vp9_encoder_parms_get_to_decoder.cc
+endif
+
+LIBVPX_TEST_SRCS-yes                   += convolve_test.cc
+LIBVPX_TEST_SRCS-yes                   += lpf_8_test.cc
+LIBVPX_TEST_SRCS-yes                   += vp9_intrapred_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_decrypt_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_DECODER) += vp9_thread_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct16x16_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += dct32x32_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct4x4_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += fdct8x8_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += hadamard_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += minmax_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += variance_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_error_block_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_quantize_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_subtract_test.cc
+
+ifeq ($(CONFIG_VP9_ENCODER),yes)
+LIBVPX_TEST_SRCS-$(CONFIG_SPATIAL_SVC) += svc_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += blockiness_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_INTERNAL_STATS) += consistency_test.cc
+endif
+
+ifeq ($(CONFIG_VP9_ENCODER)$(CONFIG_VP9_TEMPORAL_DENOISING),yesyes)
+LIBVPX_TEST_SRCS-$(HAVE_SSE2) += vp9_denoiser_sse2_test.cc
+endif
+LIBVPX_TEST_SRCS-$(CONFIG_VP9_ENCODER) += vp9_arf_freq_test.cc
+
+endif # VP9
+
+## VP10
+ifeq ($(CONFIG_VP10),yes)
+
+LIBVPX_TEST_SRCS-yes                    += vp10_inv_txfm_test.cc
+LIBVPX_TEST_SRCS-$(CONFIG_VP10_ENCODER) += vp10_dct_test.cc
+
+endif # VP10
+
+## Multi-codec / unconditional whitebox tests.
+
+ifeq ($(findstring yes,$(CONFIG_VP9_ENCODER)$(CONFIG_VP10_ENCODER)),yes)
+LIBVPX_TEST_SRCS-yes += avg_test.cc
+endif
+
+LIBVPX_TEST_SRCS-$(CONFIG_ENCODERS) += sad_test.cc
+
+TEST_INTRA_PRED_SPEED_SRCS-yes := test_intra_pred_speed.cc
+TEST_INTRA_PRED_SPEED_SRCS-yes += ../md5_utils.h ../md5_utils.c
+
+endif # CONFIG_SHARED
+
+include $(SRC_PATH_BARE)/test/test-data.mk
diff --git a/src/third_party/libvpx/test/test_intra_pred_speed.cc b/src/third_party/libvpx/test/test_intra_pred_speed.cc
new file mode 100644
index 0000000..2acf744
--- /dev/null
+++ b/src/third_party/libvpx/test/test_intra_pred_speed.cc
@@ -0,0 +1,373 @@
+/*
+ *  Copyright (c) 2015 The WebM 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 and time VPX intra-predictor functions
+
+#include <stdio.h>
+#include <string.h>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_dsp_rtcd.h"
+#include "test/acm_random.h"
+#include "test/clear_system_state.h"
+#include "test/md5_helper.h"
+#include "vpx/vpx_integer.h"
+#include "vpx_ports/mem.h"
+#include "vpx_ports/vpx_timer.h"
+
+// -----------------------------------------------------------------------------
+
+namespace {
+
+typedef void (*VpxPredFunc)(uint8_t *dst, ptrdiff_t y_stride,
+                            const uint8_t *above, const uint8_t *left);
+
+const int kNumVp9IntraPredFuncs = 13;
+const char *kVp9IntraPredNames[kNumVp9IntraPredFuncs] = {
+  "DC_PRED", "DC_LEFT_PRED", "DC_TOP_PRED", "DC_128_PRED", "V_PRED", "H_PRED",
+  "D45_PRED", "D135_PRED", "D117_PRED", "D153_PRED", "D207_PRED", "D63_PRED",
+  "TM_PRED"
+};
+
+void TestIntraPred(const char name[], VpxPredFunc const *pred_funcs,
+                   const char *const pred_func_names[], int num_funcs,
+                   const char *const signatures[], int block_size,
+                   int num_pixels_per_test) {
+  libvpx_test::ACMRandom rnd(libvpx_test::ACMRandom::DeterministicSeed());
+  const int kBPS = 32;
+  const int kTotalPixels = 32 * kBPS;
+  DECLARE_ALIGNED(16, uint8_t, src[kTotalPixels]);
+  DECLARE_ALIGNED(16, uint8_t, ref_src[kTotalPixels]);
+  DECLARE_ALIGNED(16, uint8_t, left[kBPS]);
+  DECLARE_ALIGNED(16, uint8_t, above_mem[2 * kBPS + 16]);
+  uint8_t *const above = above_mem + 16;
+  for (int i = 0; i < kTotalPixels; ++i) ref_src[i] = rnd.Rand8();
+  for (int i = 0; i < kBPS; ++i) left[i] = rnd.Rand8();
+  for (int i = -1; i < kBPS; ++i) above[i] = rnd.Rand8();
+  const int kNumTests = static_cast<int>(2.e10 / num_pixels_per_test);
+
+  // some code assumes the top row has been extended:
+  // d45/d63 C-code, for instance, but not the assembly.
+  // TODO(jzern): this style of extension isn't strictly necessary.
+  ASSERT_LE(block_size, kBPS);
+  memset(above + block_size, above[block_size - 1], 2 * kBPS - block_size);
+
+  for (int k = 0; k < num_funcs; ++k) {
+    if (pred_funcs[k] == NULL) continue;
+    memcpy(src, ref_src, sizeof(src));
+    vpx_usec_timer timer;
+    vpx_usec_timer_start(&timer);
+    for (int num_tests = 0; num_tests < kNumTests; ++num_tests) {
+      pred_funcs[k](src, kBPS, above, left);
+    }
+    libvpx_test::ClearSystemState();
+    vpx_usec_timer_mark(&timer);
+    const int elapsed_time =
+        static_cast<int>(vpx_usec_timer_elapsed(&timer) / 1000);
+    libvpx_test::MD5 md5;
+    md5.Add(src, sizeof(src));
+    printf("Mode %s[%12s]: %5d ms     MD5: %s\n", name, pred_func_names[k],
+           elapsed_time, md5.Get());
+    EXPECT_STREQ(signatures[k], md5.Get());
+  }
+}
+
+void TestIntraPred4(VpxPredFunc const *pred_funcs) {
+  static const int kNumVp9IntraFuncs = 13;
+  static const char *const kSignatures[kNumVp9IntraFuncs] = {
+    "4334156168b34ab599d9b5b30f522fe9",
+    "bc4649d5ba47c7ff178d92e475960fb0",
+    "8d316e5933326dcac24e1064794b5d12",
+    "a27270fed024eafd762c95de85f4da51",
+    "c33dff000d4256c2b8f3bf9e9bab14d2",
+    "44d8cddc2ad8f79b8ed3306051722b4f",
+    "eb54839b2bad6699d8946f01ec041cd0",
+    "ecb0d56ae5f677ea45127ce9d5c058e4",
+    "0b7936841f6813da818275944895b574",
+    "9117972ef64f91a58ff73e1731c81db2",
+    "c56d5e8c729e46825f46dd5d3b5d508a",
+    "c0889e2039bcf7bcb5d2f33cdca69adc",
+    "309a618577b27c648f9c5ee45252bc8f",
+  };
+  TestIntraPred("Intra4", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs,
+                kSignatures, 4, 4 * 4 * kNumVp9IntraFuncs);
+}
+
+void TestIntraPred8(VpxPredFunc const *pred_funcs) {
+  static const int kNumVp9IntraFuncs = 13;
+  static const char *const kSignatures[kNumVp9IntraFuncs] = {
+    "7694ddeeefed887faf9d339d18850928",
+    "7d726b1213591b99f736be6dec65065b",
+    "19c5711281357a485591aaf9c96c0a67",
+    "ba6b66877a089e71cd938e3b8c40caac",
+    "802440c93317e0f8ba93fab02ef74265",
+    "9e09a47a15deb0b9d8372824f9805080",
+    "b7c2d8c662268c0c427da412d7b0311d",
+    "78339c1c60bb1d67d248ab8c4da08b7f",
+    "5c97d70f7d47de1882a6cd86c165c8a9",
+    "8182bf60688b42205acd95e59e967157",
+    "08323400005a297f16d7e57e7fe1eaac",
+    "95f7bfc262329a5849eda66d8f7c68ce",
+    "815b75c8e0d91cc1ae766dc5d3e445a3",
+  };
+  TestIntraPred("Intra8", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs,
+                kSignatures, 8, 8 * 8 * kNumVp9IntraFuncs);
+}
+
+void TestIntraPred16(VpxPredFunc const *pred_funcs) {
+  static const int kNumVp9IntraFuncs = 13;
+  static const char *const kSignatures[kNumVp9IntraFuncs] = {
+    "b40dbb555d5d16a043dc361e6694fe53",
+    "fb08118cee3b6405d64c1fd68be878c6",
+    "6c190f341475c837cc38c2e566b64875",
+    "db5c34ccbe2c7f595d9b08b0dc2c698c",
+    "a62cbfd153a1f0b9fed13e62b8408a7a",
+    "143df5b4c89335e281103f610f5052e4",
+    "d87feb124107cdf2cfb147655aa0bb3c",
+    "7841fae7d4d47b519322e6a03eeed9dc",
+    "f6ebed3f71cbcf8d6d0516ce87e11093",
+    "3cc480297dbfeed01a1c2d78dd03d0c5",
+    "b9f69fa6532b372c545397dcb78ef311",
+    "a8fe1c70432f09d0c20c67bdb6432c4d",
+    "b8a41aa968ec108af447af4217cba91b",
+  };
+  TestIntraPred("Intra16", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs,
+                kSignatures, 16, 16 * 16 * kNumVp9IntraFuncs);
+}
+
+void TestIntraPred32(VpxPredFunc const *pred_funcs) {
+  static const int kNumVp9IntraFuncs = 13;
+  static const char *const kSignatures[kNumVp9IntraFuncs] = {
+    "558541656d84f9ae7896db655826febe",
+    "b3587a1f9a01495fa38c8cd3c8e2a1bf",
+    "4c6501e64f25aacc55a2a16c7e8f0255",
+    "b3b01379ba08916ef6b1b35f7d9ad51c",
+    "0f1eb38b6cbddb3d496199ef9f329071",
+    "911c06efb9ed1c3b4c104b232b55812f",
+    "9225beb0ddfa7a1d24eaa1be430a6654",
+    "0a6d584a44f8db9aa7ade2e2fdb9fc9e",
+    "b01c9076525216925f3456f034fb6eee",
+    "d267e20ad9e5cd2915d1a47254d3d149",
+    "ed012a4a5da71f36c2393023184a0e59",
+    "f162b51ed618d28b936974cff4391da5",
+    "9e1370c6d42e08d357d9612c93a71cfc",
+  };
+  TestIntraPred("Intra32", pred_funcs, kVp9IntraPredNames, kNumVp9IntraFuncs,
+                kSignatures, 32, 32 * 32 * kNumVp9IntraFuncs);
+}
+
+}  // namespace
+
+// Defines a test case for |arch| (e.g., C, SSE2, ...) passing the predictors
+// to |test_func|. The test name is 'arch.test_func', e.g., C.TestIntraPred4.
+#define INTRA_PRED_TEST(arch, test_func, dc, dc_left, dc_top, dc_128, v, h, \
+                        d45, d135, d117, d153, d207, d63, tm)               \
+  TEST(arch, test_func) {                                                   \
+    static const VpxPredFunc vpx_intra_pred[] = {                           \
+        dc,   dc_left, dc_top, dc_128, v,   h, d45,                         \
+        d135, d117,    d153,   d207,   d63, tm};                            \
+    test_func(vpx_intra_pred);                                              \
+  }
+
+// -----------------------------------------------------------------------------
+// 4x4
+
+INTRA_PRED_TEST(C, TestIntraPred4, vpx_dc_predictor_4x4_c,
+                vpx_dc_left_predictor_4x4_c, vpx_dc_top_predictor_4x4_c,
+                vpx_dc_128_predictor_4x4_c, vpx_v_predictor_4x4_c,
+                vpx_h_predictor_4x4_c, vpx_d45_predictor_4x4_c,
+                vpx_d135_predictor_4x4_c, vpx_d117_predictor_4x4_c,
+                vpx_d153_predictor_4x4_c, vpx_d207_predictor_4x4_c,
+                vpx_d63_predictor_4x4_c, vpx_tm_predictor_4x4_c)
+
+#if HAVE_SSE2 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSE2, TestIntraPred4, vpx_dc_predictor_4x4_sse2,
+                vpx_dc_left_predictor_4x4_sse2, vpx_dc_top_predictor_4x4_sse2,
+                vpx_dc_128_predictor_4x4_sse2, vpx_v_predictor_4x4_sse2,
+                vpx_h_predictor_4x4_sse2, vpx_d45_predictor_4x4_sse2, NULL,
+                NULL, NULL, vpx_d207_predictor_4x4_sse2, NULL,
+                vpx_tm_predictor_4x4_sse2)
+#endif  // HAVE_SSE2 && CONFIG_USE_X86INC
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSSE3, TestIntraPred4, NULL, NULL, NULL, NULL, NULL,
+                NULL, NULL, NULL, NULL,
+                vpx_d153_predictor_4x4_ssse3, NULL,
+                vpx_d63_predictor_4x4_ssse3, NULL)
+#endif  // HAVE_SSSE3 && CONFIG_USE_X86INC
+
+#if HAVE_DSPR2
+INTRA_PRED_TEST(DSPR2, TestIntraPred4, vpx_dc_predictor_4x4_dspr2, NULL, NULL,
+                NULL, NULL, vpx_h_predictor_4x4_dspr2, NULL, NULL, NULL, NULL,
+                NULL, NULL, vpx_tm_predictor_4x4_dspr2)
+#endif  // HAVE_DSPR2
+
+#if HAVE_NEON
+INTRA_PRED_TEST(NEON, TestIntraPred4, vpx_dc_predictor_4x4_neon,
+                vpx_dc_left_predictor_4x4_neon, vpx_dc_top_predictor_4x4_neon,
+                vpx_dc_128_predictor_4x4_neon, vpx_v_predictor_4x4_neon,
+                vpx_h_predictor_4x4_neon, vpx_d45_predictor_4x4_neon,
+                vpx_d135_predictor_4x4_neon, NULL, NULL, NULL, NULL,
+                vpx_tm_predictor_4x4_neon)
+#endif  // HAVE_NEON
+
+#if HAVE_MSA
+INTRA_PRED_TEST(MSA, TestIntraPred4, vpx_dc_predictor_4x4_msa,
+                vpx_dc_left_predictor_4x4_msa, vpx_dc_top_predictor_4x4_msa,
+                vpx_dc_128_predictor_4x4_msa, vpx_v_predictor_4x4_msa,
+                vpx_h_predictor_4x4_msa, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_tm_predictor_4x4_msa)
+#endif  // HAVE_MSA
+
+// -----------------------------------------------------------------------------
+// 8x8
+
+INTRA_PRED_TEST(C, TestIntraPred8, vpx_dc_predictor_8x8_c,
+                vpx_dc_left_predictor_8x8_c, vpx_dc_top_predictor_8x8_c,
+                vpx_dc_128_predictor_8x8_c, vpx_v_predictor_8x8_c,
+                vpx_h_predictor_8x8_c, vpx_d45_predictor_8x8_c,
+                vpx_d135_predictor_8x8_c, vpx_d117_predictor_8x8_c,
+                vpx_d153_predictor_8x8_c, vpx_d207_predictor_8x8_c,
+                vpx_d63_predictor_8x8_c, vpx_tm_predictor_8x8_c)
+
+#if HAVE_SSE2 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSE2, TestIntraPred8, vpx_dc_predictor_8x8_sse2,
+                vpx_dc_left_predictor_8x8_sse2, vpx_dc_top_predictor_8x8_sse2,
+                vpx_dc_128_predictor_8x8_sse2, vpx_v_predictor_8x8_sse2,
+                vpx_h_predictor_8x8_sse2, vpx_d45_predictor_8x8_sse2, NULL,
+                NULL, NULL, NULL, NULL, vpx_tm_predictor_8x8_sse2)
+#endif  // HAVE_SSE2 && CONFIG_USE_X86INC
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSSE3, TestIntraPred8, NULL, NULL, NULL, NULL, NULL,
+                NULL, NULL, NULL, NULL,
+                vpx_d153_predictor_8x8_ssse3, vpx_d207_predictor_8x8_ssse3,
+                vpx_d63_predictor_8x8_ssse3, NULL)
+#endif  // HAVE_SSSE3 && CONFIG_USE_X86INC
+
+#if HAVE_DSPR2
+INTRA_PRED_TEST(DSPR2, TestIntraPred8, vpx_dc_predictor_8x8_dspr2, NULL, NULL,
+                NULL, NULL, vpx_h_predictor_8x8_dspr2, NULL, NULL, NULL, NULL,
+                NULL, NULL, vpx_tm_predictor_8x8_c)
+#endif  // HAVE_DSPR2
+
+#if HAVE_NEON
+INTRA_PRED_TEST(NEON, TestIntraPred8, vpx_dc_predictor_8x8_neon,
+                vpx_dc_left_predictor_8x8_neon, vpx_dc_top_predictor_8x8_neon,
+                vpx_dc_128_predictor_8x8_neon, vpx_v_predictor_8x8_neon,
+                vpx_h_predictor_8x8_neon, vpx_d45_predictor_8x8_neon, NULL,
+                NULL, NULL, NULL, NULL, vpx_tm_predictor_8x8_neon)
+
+#endif  // HAVE_NEON
+
+#if HAVE_MSA
+INTRA_PRED_TEST(MSA, TestIntraPred8, vpx_dc_predictor_8x8_msa,
+                vpx_dc_left_predictor_8x8_msa, vpx_dc_top_predictor_8x8_msa,
+                vpx_dc_128_predictor_8x8_msa, vpx_v_predictor_8x8_msa,
+                vpx_h_predictor_8x8_msa, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_tm_predictor_8x8_msa)
+#endif  // HAVE_MSA
+
+// -----------------------------------------------------------------------------
+// 16x16
+
+INTRA_PRED_TEST(C, TestIntraPred16, vpx_dc_predictor_16x16_c,
+                vpx_dc_left_predictor_16x16_c, vpx_dc_top_predictor_16x16_c,
+                vpx_dc_128_predictor_16x16_c, vpx_v_predictor_16x16_c,
+                vpx_h_predictor_16x16_c, vpx_d45_predictor_16x16_c,
+                vpx_d135_predictor_16x16_c, vpx_d117_predictor_16x16_c,
+                vpx_d153_predictor_16x16_c, vpx_d207_predictor_16x16_c,
+                vpx_d63_predictor_16x16_c, vpx_tm_predictor_16x16_c)
+
+#if HAVE_SSE2 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSE2, TestIntraPred16, vpx_dc_predictor_16x16_sse2,
+                vpx_dc_left_predictor_16x16_sse2,
+                vpx_dc_top_predictor_16x16_sse2,
+                vpx_dc_128_predictor_16x16_sse2, vpx_v_predictor_16x16_sse2,
+                vpx_h_predictor_16x16_sse2, NULL, NULL, NULL, NULL, NULL, NULL,
+                vpx_tm_predictor_16x16_sse2)
+#endif  // HAVE_SSE2 && CONFIG_USE_X86INC
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSSE3, TestIntraPred16, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_d45_predictor_16x16_ssse3,
+                NULL, NULL, vpx_d153_predictor_16x16_ssse3,
+                vpx_d207_predictor_16x16_ssse3, vpx_d63_predictor_16x16_ssse3,
+                NULL)
+#endif  // HAVE_SSSE3 && CONFIG_USE_X86INC
+
+#if HAVE_DSPR2
+INTRA_PRED_TEST(DSPR2, TestIntraPred16, vpx_dc_predictor_16x16_dspr2, NULL,
+                NULL, NULL, NULL, vpx_h_predictor_16x16_dspr2, NULL, NULL, NULL,
+                NULL, NULL, NULL, NULL)
+#endif  // HAVE_DSPR2
+
+#if HAVE_NEON
+INTRA_PRED_TEST(NEON, TestIntraPred16, vpx_dc_predictor_16x16_neon,
+                vpx_dc_left_predictor_16x16_neon,
+                vpx_dc_top_predictor_16x16_neon,
+                vpx_dc_128_predictor_16x16_neon, vpx_v_predictor_16x16_neon,
+                vpx_h_predictor_16x16_neon, vpx_d45_predictor_16x16_neon, NULL,
+                NULL, NULL, NULL, NULL, vpx_tm_predictor_16x16_neon)
+#endif  // HAVE_NEON
+
+#if HAVE_MSA
+INTRA_PRED_TEST(MSA, TestIntraPred16, vpx_dc_predictor_16x16_msa,
+                vpx_dc_left_predictor_16x16_msa, vpx_dc_top_predictor_16x16_msa,
+                vpx_dc_128_predictor_16x16_msa, vpx_v_predictor_16x16_msa,
+                vpx_h_predictor_16x16_msa, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_tm_predictor_16x16_msa)
+#endif  // HAVE_MSA
+
+// -----------------------------------------------------------------------------
+// 32x32
+
+INTRA_PRED_TEST(C, TestIntraPred32, vpx_dc_predictor_32x32_c,
+                vpx_dc_left_predictor_32x32_c, vpx_dc_top_predictor_32x32_c,
+                vpx_dc_128_predictor_32x32_c, vpx_v_predictor_32x32_c,
+                vpx_h_predictor_32x32_c, vpx_d45_predictor_32x32_c,
+                vpx_d135_predictor_32x32_c, vpx_d117_predictor_32x32_c,
+                vpx_d153_predictor_32x32_c, vpx_d207_predictor_32x32_c,
+                vpx_d63_predictor_32x32_c, vpx_tm_predictor_32x32_c)
+
+#if HAVE_SSE2 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSE2, TestIntraPred32, vpx_dc_predictor_32x32_sse2,
+                vpx_dc_left_predictor_32x32_sse2,
+                vpx_dc_top_predictor_32x32_sse2,
+                vpx_dc_128_predictor_32x32_sse2, vpx_v_predictor_32x32_sse2,
+                vpx_h_predictor_32x32_sse2, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_tm_predictor_32x32_sse2)
+#endif  // HAVE_SSE2 && CONFIG_USE_X86INC
+
+#if HAVE_SSSE3 && CONFIG_USE_X86INC
+INTRA_PRED_TEST(SSSE3, TestIntraPred32, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_d45_predictor_32x32_ssse3, NULL, NULL,
+                vpx_d153_predictor_32x32_ssse3, vpx_d207_predictor_32x32_ssse3,
+                vpx_d63_predictor_32x32_ssse3, NULL)
+#endif  // HAVE_SSSE3 && CONFIG_USE_X86INC
+
+#if HAVE_NEON
+INTRA_PRED_TEST(NEON, TestIntraPred32, vpx_dc_predictor_32x32_neon,
+                vpx_dc_left_predictor_32x32_neon,
+                vpx_dc_top_predictor_32x32_neon,
+                vpx_dc_128_predictor_32x32_neon, vpx_v_predictor_32x32_neon,
+                vpx_h_predictor_32x32_neon, NULL, NULL, NULL, NULL, NULL, NULL,
+                vpx_tm_predictor_32x32_neon)
+#endif  // HAVE_NEON
+
+#if HAVE_MSA
+INTRA_PRED_TEST(MSA, TestIntraPred32, vpx_dc_predictor_32x32_msa,
+                vpx_dc_left_predictor_32x32_msa, vpx_dc_top_predictor_32x32_msa,
+                vpx_dc_128_predictor_32x32_msa, vpx_v_predictor_32x32_msa,
+                vpx_h_predictor_32x32_msa, NULL, NULL, NULL, NULL, NULL,
+                NULL, vpx_tm_predictor_32x32_msa)
+#endif  // HAVE_MSA
+
+#include "test/test_libvpx.cc"
diff --git a/src/third_party/libvpx/test/test_libvpx.cc b/src/third_party/libvpx/test/test_libvpx.cc
new file mode 100644
index 0000000..005ea8d
--- /dev/null
+++ b/src/third_party/libvpx/test/test_libvpx.cc
@@ -0,0 +1,77 @@
+/*
+ *  Copyright (c) 2012 The WebM 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>
+
+#include "third_party/googletest/src/include/gtest/gtest.h"
+
+#include "./vpx_config.h"
+#if ARCH_X86 || ARCH_X86_64
+#include "vpx_ports/x86.h"
+#endif
+extern "C" {
+#if CONFIG_VP8
+extern void vp8_rtcd();
+#endif  // CONFIG_VP8
+#if CONFIG_VP9
+extern void vp9_rtcd();
+#endif  // CONFIG_VP9
+extern void vpx_dsp_rtcd();
+extern void vpx_scale_rtcd();
+}
+
+#if ARCH_X86 || ARCH_X86_64
+static void append_negative_gtest_filter(const char *str) {
+  std::string filter = ::testing::FLAGS_gtest_filter;
+  // Negative patterns begin with one '-' followed by a ':' separated list.
+  if (filter.find('-') == std::string::npos) filter += '-';
+  filter += str;
+  ::testing::FLAGS_gtest_filter = filter;
+}
+#endif  // ARCH_X86 || ARCH_X86_64
+
+int main(int argc, char **argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+
+#if ARCH_X86 || ARCH_X86_64
+  const int simd_caps = x86_simd_caps();
+  if (!(simd_caps & HAS_MMX))
+    append_negative_gtest_filter(":MMX.*:MMX/*");
+  if (!(simd_caps & HAS_SSE))
+    append_negative_gtest_filter(":SSE.*:SSE/*");
+  if (!(simd_caps & HAS_SSE2))
+    append_negative_gtest_filter(":SSE2.*:SSE2/*");
+  if (!(simd_caps & HAS_SSE3))
+    append_negative_gtest_filter(":SSE3.*:SSE3/*");
+  if (!(simd_caps & HAS_SSSE3))
+    append_negative_gtest_filter(":SSSE3.*:SSSE3/*");
+  if (!(simd_caps & HAS_SSE4_1))
+    append_negative_gtest_filter(":SSE4_1.*:SSE4_1/*");
+  if (!(simd_caps & HAS_AVX))
+    append_negative_gtest_filter(":AVX.*:AVX/*");
+  if (!(simd_caps & HAS_AVX2))
+    append_negative_gtest_filter(":AVX2.*:AVX2/*");
+#endif  // ARCH_X86 || ARCH_X86_64
+
+#if !CONFIG_SHARED
+// Shared library builds don't support whitebox tests
+// that exercise internal symbols.
+
+#if CONFIG_VP8
+  vp8_rtcd();
+#endif  // CONFIG_VP8
+#if CONFIG_VP9
+  vp9_rtcd();
+#endif  // CONFIG_VP9
+  vpx_dsp_rtcd();
+  vpx_scale_rtcd();
+#endif  // !CONFIG_SHARED
+
+  return RUN_ALL_TESTS();
+}
diff --git a/src/third_party/libvpx/test/test_vector_test.cc b/src/third_party/libvpx/test/test_vector_test.cc
new file mode 100644
index 0000000..f1aa4d7
--- /dev/null
+++ b/src/third_party/libvpx/test/test_vector_test.cc
@@ -0,0 +1,192 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 <cstdio>
+#include <cstdlib>
+#include <set>
+#include <string>
+#include "third_party/googletest/src/include/gtest/gtest.h"
+#include "../tools_common.h"
+#include "./vpx_config.h"
+#include "test/codec_factory.h"
+#include "test/decode_test_driver.h"
+#include "test/ivf_video_source.h"
+#include "test/md5_helper.h"
+#include "test/test_vectors.h"
+#include "test/util.h"
+#if CONFIG_WEBM_IO
+#include "test/webm_video_source.h"
+#endif
+#include "vpx_mem/vpx_mem.h"
+
+namespace {
+
+enum DecodeMode {
+  kSerialMode,
+  kFrameParallelMode
+};
+
+const int kDecodeMode = 0;
+const int kThreads = 1;
+const int kFileName = 2;
+
+typedef std::tr1::tuple<int, int, const char*> DecodeParam;
+
+class TestVectorTest : public ::libvpx_test::DecoderTest,
+    public ::libvpx_test::CodecTestWithParam<DecodeParam> {
+ protected:
+  TestVectorTest()
+      : DecoderTest(GET_PARAM(0)),
+        md5_file_(NULL) {
+#if CONFIG_VP9_DECODER
+    resize_clips_.insert(
+      ::libvpx_test::kVP9TestVectorsResize,
+      ::libvpx_test::kVP9TestVectorsResize +
+          ::libvpx_test::kNumVP9TestVectorsResize);
+#endif
+  }
+
+  virtual ~TestVectorTest() {
+    if (md5_file_)
+      fclose(md5_file_);
+  }
+
+  void OpenMD5File(const std::string& md5_file_name_) {
+    md5_file_ = libvpx_test::OpenTestDataFile(md5_file_name_);
+    ASSERT_TRUE(md5_file_ != NULL) << "Md5 file open failed. Filename: "
+        << md5_file_name_;
+  }
+
+  virtual void DecompressedFrameHook(const vpx_image_t& img,
+                                     const unsigned int frame_number) {
+    ASSERT_TRUE(md5_file_ != NULL);
+    char expected_md5[33];
+    char junk[128];
+
+    // Read correct md5 checksums.
+    const int res = fscanf(md5_file_, "%s  %s", expected_md5, junk);
+    ASSERT_NE(res, EOF) << "Read md5 data failed";
+    expected_md5[32] = '\0';
+
+    ::libvpx_test::MD5 md5_res;
+    md5_res.Add(&img);
+    const char *actual_md5 = md5_res.Get();
+
+    // Check md5 match.
+    ASSERT_STREQ(expected_md5, actual_md5)
+        << "Md5 checksums don't match: frame number = " << frame_number;
+  }
+
+#if CONFIG_VP9_DECODER
+  std::set<std::string> resize_clips_;
+#endif
+
+ private:
+  FILE *md5_file_;
+};
+
+// This test runs through the whole set of test vectors, and decodes them.
+// The md5 checksums are computed for each frame in the video file. If md5
+// checksums match the correct md5 data, then the test is passed. Otherwise,
+// the test failed.
+TEST_P(TestVectorTest, MD5Match) {
+  const DecodeParam input = GET_PARAM(1);
+  const std::string filename = std::tr1::get<kFileName>(input);
+  const int threads = std::tr1::get<kThreads>(input);
+  const int mode = std::tr1::get<kDecodeMode>(input);
+  libvpx_test::CompressedVideoSource *video = NULL;
+  vpx_codec_flags_t flags = 0;
+  vpx_codec_dec_cfg_t cfg = vpx_codec_dec_cfg_t();
+  char str[256];
+
+  if (mode == kFrameParallelMode) {
+    flags |= VPX_CODEC_USE_FRAME_THREADING;
+#if CONFIG_VP9_DECODER
+    // TODO(hkuang): Fix frame parallel decode bug. See issue 1086.
+    if (resize_clips_.find(filename) != resize_clips_.end()) {
+      printf("Skipping the test file: %s, due to frame parallel decode bug.\n",
+             filename.c_str());
+      return;
+    }
+#endif
+  }
+
+  cfg.threads = threads;
+
+  snprintf(str, sizeof(str) / sizeof(str[0]) - 1,
+           "file: %s  mode: %s threads: %d",
+           filename.c_str(), mode == 0 ? "Serial" : "Parallel", threads);
+  SCOPED_TRACE(str);
+
+  // Open compressed video file.
+  if (filename.substr(filename.length() - 3, 3) == "ivf") {
+    video = new libvpx_test::IVFVideoSource(filename);
+  } else if (filename.substr(filename.length() - 4, 4) == "webm") {
+#if CONFIG_WEBM_IO
+    video = new libvpx_test::WebMVideoSource(filename);
+#else
+    fprintf(stderr, "WebM IO is disabled, skipping test vector %s\n",
+            filename.c_str());
+    return;
+#endif
+  }
+  video->Init();
+
+  // Construct md5 file name.
+  const std::string md5_filename = filename + ".md5";
+  OpenMD5File(md5_filename);
+
+  // Set decode config and flags.
+  set_cfg(cfg);
+  set_flags(flags);
+
+  // Decode frame, and check the md5 matching.
+  ASSERT_NO_FATAL_FAILURE(RunLoop(video, cfg));
+  delete video;
+}
+
+// Test VP8 decode in serial mode with single thread.
+// NOTE: VP8 only support serial mode.
+#if CONFIG_VP8_DECODER
+VP8_INSTANTIATE_TEST_CASE(
+    TestVectorTest,
+    ::testing::Combine(
+        ::testing::Values(0),  // Serial Mode.
+        ::testing::Values(1),  // Single thread.
+        ::testing::ValuesIn(libvpx_test::kVP8TestVectors,
+                            libvpx_test::kVP8TestVectors +
+                                libvpx_test::kNumVP8TestVectors)));
+#endif  // CONFIG_VP8_DECODER
+
+// Test VP9 decode in serial mode with single thread.
+#if CONFIG_VP9_DECODER
+VP9_INSTANTIATE_TEST_CASE(
+    TestVectorTest,
+    ::testing::Combine(
+        ::testing::Values(0),  // Serial Mode.
+        ::testing::Values(1),  // Single thread.
+        ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+                            libvpx_test::kVP9TestVectors +
+                                libvpx_test::kNumVP9TestVectors)));
+
+// Test VP9 decode in frame parallel mode with different number of threads.
+INSTANTIATE_TEST_CASE_P(
+    VP9MultiThreadedFrameParallel, TestVectorTest,
+    ::testing::Combine(
+        ::testing::Values(
+            static_cast<const libvpx_test::CodecFactory *>(&libvpx_test::kVP9)),
+        ::testing::Combine(
+            ::testing::Values(1),        // Frame Parallel mode.
+            ::testing::Range(2, 9),      // With 2 ~ 8 threads.
+            ::testing::ValuesIn(libvpx_test::kVP9TestVectors,
+                                libvpx_test::kVP9TestVectors +
+                                    libvpx_test::kNumVP9TestVectors))));
+#endif
+}  // namespace
diff --git a/src/third_party/libvpx/test/test_vectors.cc b/src/third_party/libvpx/test/test_vectors.cc
new file mode 100644
index 0000000..c822479
--- /dev/null
+++ b/src/third_party/libvpx/test/test_vectors.cc
@@ -0,0 +1,251 @@
+/*
+ *  Copyright (c) 2013 The WebM 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 "test/test_vectors.h"
+
+namespace libvpx_test {
+
+#define NELEMENTS(x) static_cast<int>(sizeof(x) / sizeof(x[0]))
+
+#if CONFIG_VP8_DECODER
+const char *const kVP8TestVectors[] = {
+  "vp80-00-comprehensive-001.ivf",
+  "vp80-00-comprehensive-002.ivf", "vp80-00-comprehensive-003.ivf",
+  "vp80-00-comprehensive-004.ivf", "vp80-00-comprehensive-005.ivf",
+  "vp80-00-comprehensive-006.ivf", "vp80-00-comprehensive-007.ivf",
+  "vp80-00-comprehensive-008.ivf", "vp80-00-comprehensive-009.ivf",
+  "vp80-00-comprehensive-010.ivf", "vp80-00-comprehensive-011.ivf",
+  "vp80-00-comprehensive-012.ivf", "vp80-00-comprehensive-013.ivf",
+  "vp80-00-comprehensive-014.ivf", "vp80-00-comprehensive-015.ivf",
+  "vp80-00-comprehensive-016.ivf", "vp80-00-comprehensive-017.ivf",
+  "vp80-00-comprehensive-018.ivf", "vp80-01-intra-1400.ivf",
+  "vp80-01-intra-1411.ivf", "vp80-01-intra-1416.ivf",
+  "vp80-01-intra-1417.ivf", "vp80-02-inter-1402.ivf",
+  "vp80-02-inter-1412.ivf", "vp80-02-inter-1418.ivf",
+  "vp80-02-inter-1424.ivf", "vp80-03-segmentation-01.ivf",
+  "vp80-03-segmentation-02.ivf", "vp80-03-segmentation-03.ivf",
+  "vp80-03-segmentation-04.ivf", "vp80-03-segmentation-1401.ivf",
+  "vp80-03-segmentation-1403.ivf", "vp80-03-segmentation-1407.ivf",
+  "vp80-03-segmentation-1408.ivf", "vp80-03-segmentation-1409.ivf",
+  "vp80-03-segmentation-1410.ivf", "vp80-03-segmentation-1413.ivf",
+  "vp80-03-segmentation-1414.ivf", "vp80-03-segmentation-1415.ivf",
+  "vp80-03-segmentation-1425.ivf", "vp80-03-segmentation-1426.ivf",
+  "vp80-03-segmentation-1427.ivf", "vp80-03-segmentation-1432.ivf",
+  "vp80-03-segmentation-1435.ivf", "vp80-03-segmentation-1436.ivf",
+  "vp80-03-segmentation-1437.ivf", "vp80-03-segmentation-1441.ivf",
+  "vp80-03-segmentation-1442.ivf", "vp80-04-partitions-1404.ivf",
+  "vp80-04-partitions-1405.ivf", "vp80-04-partitions-1406.ivf",
+  "vp80-05-sharpness-1428.ivf", "vp80-05-sharpness-1429.ivf",
+  "vp80-05-sharpness-1430.ivf", "vp80-05-sharpness-1431.ivf",
+  "vp80-05-sharpness-1433.ivf", "vp80-05-sharpness-1434.ivf",
+  "vp80-05-sharpness-1438.ivf", "vp80-05-sharpness-1439.ivf",
+  "vp80-05-sharpness-1440.ivf", "vp80-05-sharpness-1443.ivf",
+  "vp80-06-smallsize.ivf"
+};
+const int kNumVP8TestVectors = NELEMENTS(kVP8TestVectors);
+#endif  // CONFIG_VP8_DECODER
+#if CONFIG_VP9_DECODER
+#define RESIZE_TEST_VECTORS "vp90-2-21-resize_inter_320x180_5_1-2.webm", \
+  "vp90-2-21-resize_inter_320x180_5_3-4.webm", \
+  "vp90-2-21-resize_inter_320x180_7_1-2.webm", \
+  "vp90-2-21-resize_inter_320x180_7_3-4.webm", \
+  "vp90-2-21-resize_inter_320x240_5_1-2.webm", \
+  "vp90-2-21-resize_inter_320x240_5_3-4.webm", \
+  "vp90-2-21-resize_inter_320x240_7_1-2.webm", \
+  "vp90-2-21-resize_inter_320x240_7_3-4.webm", \
+  "vp90-2-21-resize_inter_640x360_5_1-2.webm", \
+  "vp90-2-21-resize_inter_640x360_5_3-4.webm", \
+  "vp90-2-21-resize_inter_640x360_7_1-2.webm", \
+  "vp90-2-21-resize_inter_640x360_7_3-4.webm", \
+  "vp90-2-21-resize_inter_640x480_5_1-2.webm", \
+  "vp90-2-21-resize_inter_640x480_5_3-4.webm", \
+  "vp90-2-21-resize_inter_640x480_7_1-2.webm", \
+  "vp90-2-21-resize_inter_640x480_7_3-4.webm", \
+  "vp90-2-21-resize_inter_1280x720_5_1-2.webm", \
+  "vp90-2-21-resize_inter_1280x720_5_3-4.webm", \
+  "vp90-2-21-resize_inter_1280x720_7_1-2.webm", \
+  "vp90-2-21-resize_inter_1280x720_7_3-4.webm", \
+  "vp90-2-21-resize_inter_1920x1080_5_1-2.webm", \
+  "vp90-2-21-resize_inter_1920x1080_5_3-4.webm", \
+  "vp90-2-21-resize_inter_1920x1080_7_1-2.webm", \
+  "vp90-2-21-resize_inter_1920x1080_7_3-4.webm",
+
+const char *const kVP9TestVectors[] = {
+  "vp90-2-00-quantizer-00.webm", "vp90-2-00-quantizer-01.webm",
+  "vp90-2-00-quantizer-02.webm", "vp90-2-00-quantizer-03.webm",
+  "vp90-2-00-quantizer-04.webm", "vp90-2-00-quantizer-05.webm",
+  "vp90-2-00-quantizer-06.webm", "vp90-2-00-quantizer-07.webm",
+  "vp90-2-00-quantizer-08.webm", "vp90-2-00-quantizer-09.webm",
+  "vp90-2-00-quantizer-10.webm", "vp90-2-00-quantizer-11.webm",
+  "vp90-2-00-quantizer-12.webm", "vp90-2-00-quantizer-13.webm",
+  "vp90-2-00-quantizer-14.webm", "vp90-2-00-quantizer-15.webm",