Add VP9 codec to VCM and vie_auto_test.
Include VP9 tests in videoprocessor_integrationtests.
Include end-to-end send/receiveVP9 test.

This is the same patch as https://code.google.com/p/webrtc/source/detail?r=7422, which was reverted when rolled into chrome (due to bss size increase). Relanding this again as we now have the clear to get this in:
see https://code.google.com/p/webrtc/issues/detail?id=3932

R=kjellander@webrtc.org, mflodman@webrtc.org, stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/31829004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@7588 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/build/common.gypi b/webrtc/build/common.gypi
index e89f2f2..366e7e9 100644
--- a/webrtc/build/common.gypi
+++ b/webrtc/build/common.gypi
@@ -42,6 +42,7 @@
       'modules_java_gyp_path%': '<(modules_java_gyp_path)',
       'gen_core_neon_offsets_gyp%': '<(gen_core_neon_offsets_gyp)',
       'webrtc_vp8_dir%': '<(webrtc_root)/modules/video_coding/codecs/vp8',
+      'webrtc_vp9_dir%': '<(webrtc_root)/modules/video_coding/codecs/vp9',
       'rbe_components_path%': '<(webrtc_root)/modules/remote_bitrate_estimator',
       'include_opus%': 1,
     },
@@ -52,6 +53,7 @@
     'modules_java_gyp_path%': '<(modules_java_gyp_path)',
     'gen_core_neon_offsets_gyp%': '<(gen_core_neon_offsets_gyp)',
     'webrtc_vp8_dir%': '<(webrtc_vp8_dir)',
+    'webrtc_vp9_dir%': '<(webrtc_vp9_dir)',
     'include_opus%': '<(include_opus)',
     'rtc_relative_path%': 1,
     'rbe_components_path%': '<(rbe_components_path)',
diff --git a/webrtc/build/tsan_suppressions_webrtc.cc b/webrtc/build/tsan_suppressions_webrtc.cc
index 723e62a..01658ed 100644
--- a/webrtc/build/tsan_suppressions_webrtc.cc
+++ b/webrtc/build/tsan_suppressions_webrtc.cc
@@ -27,6 +27,7 @@
 "race:rtc::MessageQueue::Quit\n"
 "race:FileVideoCapturerTest::VideoCapturerListener::OnFrameCaptured\n"
 "race:vp8cx_remove_encoder_threads\n"
+"race:third_party/libvpx/source/libvpx/vp9/common/vp9_scan.h\n"
 
 // Usage of trace callback and trace level is racy in libjingle_media_unittests.
 // https://code.google.com/p/webrtc/issues/detail?id=3372
diff --git a/webrtc/common_types.h b/webrtc/common_types.h
index 8a20e5e..7bcfd6d 100644
--- a/webrtc/common_types.h
+++ b/webrtc/common_types.h
@@ -611,35 +611,45 @@
   }
 };
 
+// VP9 specific
+struct VideoCodecVP9 {
+  VideoCodecComplexity complexity;
+  int                  resilience;
+  unsigned char        numberOfTemporalLayers;
+  bool                 denoisingOn;
+  bool                 frameDroppingOn;
+  int                  keyFrameInterval;
+  bool                 adaptiveQpMode;
+};
+
 // H264 specific.
-struct VideoCodecH264
-{
-    VideoCodecProfile profile;
-    bool           frameDroppingOn;
-    int            keyFrameInterval;
-    // These are NULL/0 if not externally negotiated.
-    const uint8_t* spsData;
-    size_t         spsLen;
-    const uint8_t* ppsData;
-    size_t         ppsLen;
+struct VideoCodecH264 {
+  VideoCodecProfile profile;
+  bool           frameDroppingOn;
+  int            keyFrameInterval;
+  // These are NULL/0 if not externally negotiated.
+  const uint8_t* spsData;
+  size_t         spsLen;
+  const uint8_t* ppsData;
+  size_t         ppsLen;
 };
 
 // Video codec types
-enum VideoCodecType
-{
-    kVideoCodecVP8,
-    kVideoCodecH264,
-    kVideoCodecI420,
-    kVideoCodecRED,
-    kVideoCodecULPFEC,
-    kVideoCodecGeneric,
-    kVideoCodecUnknown
+enum VideoCodecType {
+  kVideoCodecVP8,
+  kVideoCodecVP9,
+  kVideoCodecH264,
+  kVideoCodecI420,
+  kVideoCodecRED,
+  kVideoCodecULPFEC,
+  kVideoCodecGeneric,
+  kVideoCodecUnknown
 };
 
-union VideoCodecUnion
-{
-    VideoCodecVP8       VP8;
-    VideoCodecH264      H264;
+union VideoCodecUnion {
+  VideoCodecVP8       VP8;
+  VideoCodecVP9       VP9;
+  VideoCodecH264      H264;
 };
 
 
diff --git a/webrtc/engine_configurations.h b/webrtc/engine_configurations.h
index a91532f..5b093e5 100644
--- a/webrtc/engine_configurations.h
+++ b/webrtc/engine_configurations.h
@@ -51,6 +51,7 @@
 
 #define VIDEOCODEC_I420
 #define VIDEOCODEC_VP8
+#define VIDEOCODEC_VP9
 #define VIDEOCODEC_H264
 
 // ============================================================================
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index 6d0de1e..3caf41f 100644
--- a/webrtc/modules/modules.gyp
+++ b/webrtc/modules/modules.gyp
@@ -97,6 +97,7 @@
             '<(webrtc_root)/common_audio/common_audio.gyp:common_audio',
             '<(webrtc_root)/modules/modules.gyp:video_capture_module_impl',
             '<(webrtc_root)/modules/video_coding/codecs/vp8/vp8.gyp:webrtc_vp8',
+            '<(webrtc_root)/modules/video_coding/codecs/vp9/vp9.gyp:webrtc_vp9',
             '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
             '<(webrtc_root)/test/test.gyp:frame_generator',
             '<(webrtc_root)/test/test.gyp:rtp_test_utils',
@@ -326,6 +327,7 @@
             '<(DEPTH)/testing/gtest.gyp:gtest',
             '<(webrtc_root)/common_video/common_video.gyp:common_video',
             '<(webrtc_root)/modules/video_coding/codecs/vp8/vp8.gyp:webrtc_vp8',
+            '<(webrtc_root)/modules/video_coding/codecs/vp9/vp9.gyp:webrtc_vp9',
             '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
             '<(webrtc_root)/test/metrics.gyp:metrics',
             '<(webrtc_root)/test/test.gyp:test_support',
diff --git a/webrtc/modules/video_coding/BUILD.gn b/webrtc/modules/video_coding/BUILD.gn
index 07e7afc..706e9d9 100644
--- a/webrtc/modules/video_coding/BUILD.gn
+++ b/webrtc/modules/video_coding/BUILD.gn
@@ -77,6 +77,7 @@
     ":video_coding_utility",
     ":webrtc_i420",
     ":webrtc_vp8",
+    ":webrtc_vp9",
     "../../common_video",
     "../../system_wrappers",
   ]
@@ -159,3 +160,35 @@
     ]
   }
 }
+
+source_set("webrtc_vp9") {
+  sources = [
+    "codecs/vp9/include/vp9.h",
+    "codecs/vp9/vp9_impl.cc",
+    "codecs/vp9/vp9_impl.h",
+  ]
+
+  configs += [ "../..:common_config" ]
+  public_configs = [ "../..:common_inherited_config" ]
+
+  if (is_clang) {
+    # Suppress warnings from Chrome's Clang plugins.
+    # See http://code.google.com/p/webrtc/issues/detail?id=163 for details.
+    configs -= [ "//build/config/clang:find_bad_constructs" ]
+  }
+
+  # TODO(kjellander): Remove once libvpx has changed it's libvpx_config to be
+  # in direct_dependent_configs.
+  configs += [ "//third_party/libvpx:libvpx_config" ]
+
+  deps = [
+    ":video_coding_utility",
+    "../../common_video",
+    "../../system_wrappers",
+  ]
+  if (rtc_build_libvpx) {
+    deps += [
+      "//third_party/libvpx",
+    ]
+  }
+}
diff --git a/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h b/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
index 1c1d6ed..da72feb 100644
--- a/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
+++ b/webrtc/modules/video_coding/codecs/interface/video_codec_interface.h
@@ -42,6 +42,19 @@
   int8_t keyIdx;  // Negative value to skip keyIdx.
 };
 
+struct CodecSpecificInfoVP9 {
+  bool hasReceivedSLI;
+  uint8_t pictureIdSLI;
+  bool hasReceivedRPSI;
+  uint64_t pictureIdRPSI;
+  int16_t pictureId;  // Negative value to skip pictureId.
+  bool nonReference;
+  uint8_t temporalIdx;
+  bool layerSync;
+  int tl0PicIdx;  // Negative value to skip tl0PicIdx.
+  int8_t keyIdx;  // Negative value to skip keyIdx.
+};
+
 struct CodecSpecificInfoGeneric {
   uint8_t simulcast_idx;
 };
@@ -51,6 +64,7 @@
 union CodecSpecificInfoUnion {
   CodecSpecificInfoGeneric generic;
   CodecSpecificInfoVP8 VP8;
+  CodecSpecificInfoVP9 VP9;
   CodecSpecificInfoH264 H264;
 };
 
diff --git a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
index bd4a563..69f4d67 100644
--- a/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
+++ b/webrtc/modules/video_coding/codecs/test/videoprocessor_integrationtest.cc
@@ -16,6 +16,7 @@
 #include "webrtc/modules/video_coding/codecs/test/packet_manipulator.h"
 #include "webrtc/modules/video_coding/codecs/test/videoprocessor.h"
 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8_common_types.h"
 #include "webrtc/modules/video_coding/main/interface/video_coding.h"
 #include "webrtc/test/testsupport/fileutils.h"
@@ -37,6 +38,7 @@
 
 // Codec and network settings.
 struct CodecConfigPars {
+  VideoCodecType codec_type;
   float packet_loss;
   int num_temporal_layers;
   int key_frame_interval;
@@ -136,6 +138,7 @@
   float start_bitrate_;
 
   // Codec and network settings.
+  VideoCodecType codec_type_;
   float packet_loss_;
   int num_temporal_layers_;
   int key_frame_interval_;
@@ -149,8 +152,15 @@
   virtual ~VideoProcessorIntegrationTest() {}
 
   void SetUpCodecConfig() {
-    encoder_ = VP8Encoder::Create();
-    decoder_ = VP8Decoder::Create();
+    if (codec_type_ == kVideoCodecVP8) {
+      encoder_ = VP8Encoder::Create();
+      decoder_ = VP8Decoder::Create();
+      VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
+    } else if (codec_type_ == kVideoCodecVP9) {
+      encoder_ = VP9Encoder::Create();
+      decoder_ = VP9Decoder::Create();
+      VideoCodingModule::Codec(kVideoCodecVP9, &codec_settings_);
+    }
 
     // CIF is currently used for all tests below.
     // Setup the TestConfig struct for processing of a clip in CIF resolution.
@@ -169,26 +179,42 @@
     config_.keyframe_interval = key_frame_interval_;
     config_.networking_config.packet_loss_probability = packet_loss_;
 
-    // Get a codec configuration struct and configure it.
-    VideoCodingModule::Codec(kVideoCodecVP8, &codec_settings_);
+    // Configure codec settings.
     config_.codec_settings = &codec_settings_;
     config_.codec_settings->startBitrate = start_bitrate_;
     config_.codec_settings->width = kCIFWidth;
     config_.codec_settings->height = kCIFHeight;
-    // These features may be set depending on the test.
-    config_.codec_settings->codecSpecific.VP8.errorConcealmentOn =
-        error_concealment_on_;
-    config_.codec_settings->codecSpecific.VP8.denoisingOn =
-        denoising_on_;
-    config_.codec_settings->codecSpecific.VP8.numberOfTemporalLayers =
-        num_temporal_layers_;
-    config_.codec_settings->codecSpecific.VP8.frameDroppingOn =
-        frame_dropper_on_;
-    config_.codec_settings->codecSpecific.VP8.automaticResizeOn =
-        spatial_resize_on_;
-    config_.codec_settings->codecSpecific.VP8.keyFrameInterval =
-        kBaseKeyFrameInterval;
 
+    // These features may be set depending on the test.
+    switch (config_.codec_settings->codecType) {
+     case kVideoCodecVP8:
+       config_.codec_settings->codecSpecific.VP8.errorConcealmentOn =
+           error_concealment_on_;
+       config_.codec_settings->codecSpecific.VP8.denoisingOn =
+           denoising_on_;
+       config_.codec_settings->codecSpecific.VP8.numberOfTemporalLayers =
+           num_temporal_layers_;
+       config_.codec_settings->codecSpecific.VP8.frameDroppingOn =
+           frame_dropper_on_;
+       config_.codec_settings->codecSpecific.VP8.automaticResizeOn =
+           spatial_resize_on_;
+       config_.codec_settings->codecSpecific.VP8.keyFrameInterval =
+           kBaseKeyFrameInterval;
+       break;
+     case kVideoCodecVP9:
+       config_.codec_settings->codecSpecific.VP9.denoisingOn =
+           denoising_on_;
+       config_.codec_settings->codecSpecific.VP9.numberOfTemporalLayers =
+           num_temporal_layers_;
+       config_.codec_settings->codecSpecific.VP9.frameDroppingOn =
+           frame_dropper_on_;
+       config_.codec_settings->codecSpecific.VP9.keyFrameInterval =
+           kBaseKeyFrameInterval;
+       break;
+     default:
+       assert(false);
+       break;
+     }
     frame_reader_ =
         new webrtc::test::FrameReaderImpl(config_.input_filename,
                                           config_.frame_length_in_bytes);
@@ -405,6 +431,7 @@
                               CodecConfigPars process,
                               RateControlMetrics* rc_metrics) {
     // Codec/config settings.
+    codec_type_ = process.codec_type;
     start_bitrate_ = rate_profile.target_bit_rate[0];
     packet_loss_ = process.packet_loss;
     key_frame_interval_ = process.key_frame_interval;
@@ -514,6 +541,7 @@
 }
 
 void SetCodecParameters(CodecConfigPars* process_settings,
+                        VideoCodecType codec_type,
                         float packet_loss,
                         int key_frame_interval,
                         int num_temporal_layers,
@@ -521,6 +549,7 @@
                         bool denoising_on,
                         bool frame_dropper_on,
                         bool spatial_resize_on) {
+  process_settings->codec_type = codec_type;
   process_settings->packet_loss = packet_loss;
   process_settings->key_frame_interval =  key_frame_interval;
   process_settings->num_temporal_layers = num_temporal_layers,
@@ -560,7 +589,126 @@
   rc_metrics[update_index].num_spatial_resizes = num_spatial_resizes;
 }
 
-// Run with no packet loss and fixed bitrate. Quality should be very high.
+// VP9: Run with no packet loss and fixed bitrate. Quality should be very high.
+// One key frame (first frame only) in sequence. Setting |key_frame_interval|
+// to -1 below means no periodic key frames in test.
+TEST_F(VideoProcessorIntegrationTest, Process0PercentPacketLossVP9) {
+  // Bitrate and frame rate profile.
+  RateProfile rate_profile;
+  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
+  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
+  rate_profile.num_frames = kNbrFramesShort;
+  // Codec/network settings.
+  CodecConfigPars process_settings;
+  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
+                     false, true, false);
+  // Metrics for expected quality.
+  QualityMetrics quality_metrics;
+  SetQualityMetrics(&quality_metrics, 37.5, 36.0, 0.94, 0.93);
+  // Metrics for rate control.
+  RateControlMetrics rc_metrics[1];
+  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0);
+  ProcessFramesAndVerify(quality_metrics,
+                         rate_profile,
+                         process_settings,
+                         rc_metrics);
+}
+
+// VP9: Run with 5% packet loss and fixed bitrate. Quality should be a bit
+// lower. One key frame (first frame only) in sequence.
+TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLossVP9) {
+  // Bitrate and frame rate profile.
+  RateProfile rate_profile;
+  SetRateProfilePars(&rate_profile, 0, 500, 30, 0);
+  rate_profile.frame_index_rate_update[1] = kNbrFramesShort + 1;
+  rate_profile.num_frames = kNbrFramesShort;
+  // Codec/network settings.
+  CodecConfigPars process_settings;
+  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.05f, -1, 1, false,
+                     false, true, false);
+  // Metrics for expected quality.
+  QualityMetrics quality_metrics;
+  SetQualityMetrics(&quality_metrics, 17.0, 15.0, 0.45, 0.38);
+  // Metrics for rate control.
+  RateControlMetrics rc_metrics[1];
+  SetRateControlMetrics(rc_metrics, 0, 0, 40, 20, 10, 15, 0);
+  ProcessFramesAndVerify(quality_metrics,
+                         rate_profile,
+                         process_settings,
+                         rc_metrics);
+}
+
+
+// VP9: Run with no packet loss, with varying bitrate (3 rate updates):
+// low to high to medium. Check that quality and encoder response to the new
+// target rate/per-frame bandwidth (for each rate update) is within limits.
+// One key frame (first frame only) in sequence.
+TEST_F(VideoProcessorIntegrationTest, ProcessNoLossChangeBitRateVP9) {
+  // Bitrate and frame rate profile.
+  RateProfile rate_profile;
+  SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
+  SetRateProfilePars(&rate_profile, 1, 800, 30, 100);
+  SetRateProfilePars(&rate_profile, 2, 500, 30, 200);
+  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
+  rate_profile.num_frames = kNbrFramesLong;
+  // Codec/network settings.
+  CodecConfigPars process_settings;
+  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
+                     false, true, false);
+  // Metrics for expected quality.
+  QualityMetrics quality_metrics;
+  SetQualityMetrics(&quality_metrics, 36.0, 32.0, 0.90, 0.85);
+  // Metrics for rate control.
+  RateControlMetrics rc_metrics[3];
+  SetRateControlMetrics(rc_metrics, 0, 0, 30, 20, 20, 20, 0);
+  SetRateControlMetrics(rc_metrics, 1, 2, 0, 20, 20, 60, 0);
+  SetRateControlMetrics(rc_metrics, 2, 0, 0, 20, 20, 30, 0);
+  ProcessFramesAndVerify(quality_metrics,
+                         rate_profile,
+                         process_settings,
+                         rc_metrics);
+}
+
+// VP9: Run with no packet loss, with an update (decrease) in frame rate.
+// Lower frame rate means higher per-frame-bandwidth, so easier to encode.
+// At the low bitrate in this test, this means better rate control after the
+// update(s) to lower frame rate. So expect less frame drops, and max values
+// for the rate control metrics can be lower. One key frame (first frame only).
+// Note: quality after update should be higher but we currently compute quality
+// metrics averaged over whole sequence run.
+TEST_F(VideoProcessorIntegrationTest,
+       ProcessNoLossChangeFrameRateFrameDropVP9) {
+  config_.networking_config.packet_loss_probability = 0;
+  // Bitrate and frame rate profile.
+  RateProfile rate_profile;
+  SetRateProfilePars(&rate_profile, 0, 50, 24, 0);
+  SetRateProfilePars(&rate_profile, 1, 50, 15, 100);
+  SetRateProfilePars(&rate_profile, 2, 50, 10, 200);
+  rate_profile.frame_index_rate_update[3] = kNbrFramesLong + 1;
+  rate_profile.num_frames = kNbrFramesLong;
+  // Codec/network settings.
+  CodecConfigPars process_settings;
+  SetCodecParameters(&process_settings, kVideoCodecVP9, 0.0f, -1, 1, false,
+                     false, true, false);
+  // Metrics for expected quality.
+  QualityMetrics quality_metrics;
+  SetQualityMetrics(&quality_metrics, 30.0, 18.0, 0.80, 0.40);
+  // Metrics for rate control.
+  RateControlMetrics rc_metrics[3];
+  SetRateControlMetrics(rc_metrics, 0, 30, 30, 60, 15, 40, 0);
+  SetRateControlMetrics(rc_metrics, 1, 15, 0, 50, 10, 30, 0);
+  SetRateControlMetrics(rc_metrics, 2, 5, 0, 38, 10, 30, 0);
+  ProcessFramesAndVerify(quality_metrics,
+                         rate_profile,
+                         process_settings,
+                         rc_metrics);
+}
+
+
+// TODO(marpan): Add temporal layer test for VP9, once changes are in
+// vp9 wrapper for this.
+
+// VP8: Run with no packet loss and fixed bitrate. Quality should be very high.
 // One key frame (first frame only) in sequence. Setting |key_frame_interval|
 // to -1 below means no periodic key frames in test.
 TEST_F(VideoProcessorIntegrationTest, ProcessZeroPacketLoss) {
@@ -571,7 +719,8 @@
   rate_profile.num_frames = kNbrFramesShort;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.0f, -1, 1, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 34.95, 33.0, 0.90, 0.89);
@@ -584,8 +733,8 @@
                          rc_metrics);
 }
 
-// Run with 5% packet loss and fixed bitrate. Quality should be a bit lower.
-// One key frame (first frame only) in sequence.
+// VP8: Run with 5% packet loss and fixed bitrate. Quality should be a bit
+// lower. One key frame (first frame only) in sequence.
 TEST_F(VideoProcessorIntegrationTest, Process5PercentPacketLoss) {
   // Bitrate and frame rate profile.
   RateProfile rate_profile;
@@ -594,7 +743,8 @@
   rate_profile.num_frames = kNbrFramesShort;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.05f, -1, 1, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.05f, -1, 1, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 20.0, 16.0, 0.60, 0.40);
@@ -607,7 +757,7 @@
                          rc_metrics);
 }
 
-// Run with 10% packet loss and fixed bitrate. Quality should be even lower.
+// VP8: Run with 10% packet loss and fixed bitrate. Quality should be lower.
 // One key frame (first frame only) in sequence.
 TEST_F(VideoProcessorIntegrationTest, Process10PercentPacketLoss) {
   // Bitrate and frame rate profile.
@@ -617,7 +767,8 @@
   rate_profile.num_frames = kNbrFramesShort;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.1f, -1, 1, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.1f, -1, 1, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 19.0, 16.0, 0.50, 0.35);
@@ -639,12 +790,12 @@
 // disabled on Android. Some quality parameter in the above test has been
 // adjusted to also pass for |cpu_speed| <= 12.
 
-// Run with no packet loss, with varying bitrate (3 rate updates):
+// VP8: Run with no packet loss, with varying bitrate (3 rate updates):
 // low to high to medium. Check that quality and encoder response to the new
 // target rate/per-frame bandwidth (for each rate update) is within limits.
 // One key frame (first frame only) in sequence.
 TEST_F(VideoProcessorIntegrationTest,
-       DISABLED_ON_ANDROID(ProcessNoLossChangeBitRate)) {
+       DISABLED_ON_ANDROID(ProcessNoLossChangeBitRateVP8)) {
   // Bitrate and frame rate profile.
   RateProfile rate_profile;
   SetRateProfilePars(&rate_profile, 0, 200, 30, 0);
@@ -654,7 +805,8 @@
   rate_profile.num_frames = kNbrFramesLong;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.0f, -1, 1, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 34.0, 32.0, 0.85, 0.80);
@@ -669,15 +821,15 @@
                          rc_metrics);
 }
 
-// Run with no packet loss, with an update (decrease) in frame rate.
+// VP8: Run with no packet loss, with an update (decrease) in frame rate.
 // Lower frame rate means higher per-frame-bandwidth, so easier to encode.
 // At the bitrate in this test, this means better rate control after the
 // update(s) to lower frame rate. So expect less frame drops, and max values
 // for the rate control metrics can be lower. One key frame (first frame only).
 // Note: quality after update should be higher but we currently compute quality
-// metrics avergaed over whole sequence run.
+// metrics averaged over whole sequence run.
 TEST_F(VideoProcessorIntegrationTest,
-       DISABLED_ON_ANDROID(ProcessNoLossChangeFrameRateFrameDrop)) {
+       DISABLED_ON_ANDROID(ProcessNoLossChangeFrameRateFrameDropVP8)) {
   config_.networking_config.packet_loss_probability = 0;
   // Bitrate and frame rate profile.
   RateProfile rate_profile;
@@ -688,7 +840,8 @@
   rate_profile.num_frames = kNbrFramesLong;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.0f, -1, 1, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 1, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 31.0, 22.0, 0.80, 0.65);
@@ -706,7 +859,7 @@
 // Run with no packet loss, at low bitrate. During this time we should've
 // resized once.
 TEST_F(VideoProcessorIntegrationTest,
-       DISABLED_ON_ANDROID(ProcessNoLossSpatialResizeFrameDrop)) {
+       DISABLED_ON_ANDROID(ProcessNoLossSpatialResizeFrameDropVP8)) {
   config_.networking_config.packet_loss_probability = 0;
   // Bitrate and frame rate profile.
   RateProfile rate_profile;
@@ -715,8 +868,8 @@
   rate_profile.num_frames = kNbrFramesLong;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(
-      &process_settings, 0.0f, kNbrFramesLong, 1, false, true, true, true);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, kNbrFramesLong,
+                     1, false, true, true, true);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 25.0, 15.0, 0.70, 0.40);
@@ -729,13 +882,13 @@
                          rc_metrics);
 }
 
-// Run with no packet loss, with 3 temporal layers, with a rate update in the
-// middle of the sequence. The max values for the frame size mismatch and
+// VP8: Run with no packet loss, with 3 temporal layers, with a rate update in
+// the middle of the sequence. The max values for the frame size mismatch and
 // encoding rate mismatch are applied to each layer.
 // No dropped frames in this test, and internal spatial resizer is off.
 // One key frame (first frame only) in sequence, so no spatial resizing.
 TEST_F(VideoProcessorIntegrationTest,
-       DISABLED_ON_ANDROID(ProcessNoLossTemporalLayers)) {
+       DISABLED_ON_ANDROID(ProcessNoLossTemporalLayersVP8)) {
   config_.networking_config.packet_loss_probability = 0;
   // Bitrate and frame rate profile.
   RateProfile rate_profile;
@@ -745,7 +898,8 @@
   rate_profile.num_frames = kNbrFramesLong;
   // Codec/network settings.
   CodecConfigPars process_settings;
-  SetCodecParameters(&process_settings, 0.0f, -1, 3, false, true, true, false);
+  SetCodecParameters(&process_settings, kVideoCodecVP8, 0.0f, -1, 3, false,
+                     true, true, false);
   // Metrics for expected quality.
   QualityMetrics quality_metrics;
   SetQualityMetrics(&quality_metrics, 32.5, 30.0, 0.85, 0.80);
diff --git a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
index 08ce3c9..fec53d5 100644
--- a/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
+++ b/webrtc/modules/video_coding/codecs/vp8/vp8_impl.h
@@ -35,73 +35,20 @@
 
   virtual ~VP8EncoderImpl();
 
-  // Free encoder memory.
-  //
-  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int Release();
 
-  // Initialize the encoder with the information from the codecSettings
-  //
-  // Input:
-  //          - codec_settings    : Codec settings
-  //          - number_of_cores   : Number of cores available for the encoder
-  //          - max_payload_size  : The maximum size each payload is allowed
-  //                                to have. Usually MTU - overhead.
-  //
-  // Return value                 : Set bit rate if OK
-  //                                <0 - Errors:
-  //                                  WEBRTC_VIDEO_CODEC_ERR_PARAMETER
-  //                                  WEBRTC_VIDEO_CODEC_ERR_SIZE
-  //                                  WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED
-  //                                  WEBRTC_VIDEO_CODEC_MEMORY
-  //                                  WEBRTC_VIDEO_CODEC_ERROR
   virtual int InitEncode(const VideoCodec* codec_settings,
                          int number_of_cores,
                          uint32_t max_payload_size);
 
-  // Encode an I420 image (as a part of a video stream). The encoded image
-  // will be returned to the user through the encode complete callback.
-  //
-  // Input:
-  //          - input_image       : Image to be encoded
-  //          - frame_types       : Frame type to be generated by the encoder.
-  //
-  // Return value                 : WEBRTC_VIDEO_CODEC_OK if OK
-  //                                <0 - Errors:
-  //                                  WEBRTC_VIDEO_CODEC_ERR_PARAMETER
-  //                                  WEBRTC_VIDEO_CODEC_MEMORY
-  //                                  WEBRTC_VIDEO_CODEC_ERROR
-  //                                  WEBRTC_VIDEO_CODEC_TIMEOUT
-
   virtual int Encode(const I420VideoFrame& input_image,
                      const CodecSpecificInfo* codec_specific_info,
                      const std::vector<VideoFrameType>* frame_types);
 
-  // Register an encode complete callback object.
-  //
-  // Input:
-  //          - callback         : Callback object which handles encoded images.
-  //
-  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int RegisterEncodeCompleteCallback(EncodedImageCallback* callback);
 
-  // Inform the encoder of the new packet loss rate and the round-trip time of
-  // the network.
-  //
-  //          - packet_loss : Fraction lost
-  //                          (loss rate in percent = 100 * packetLoss / 255)
-  //          - rtt         : Round-trip time in milliseconds
-  // Return value           : WEBRTC_VIDEO_CODEC_OK if OK
-  //                          <0 - Errors: WEBRTC_VIDEO_CODEC_ERROR
-  //
   virtual int SetChannelParameters(uint32_t packet_loss, int rtt);
 
-  // Inform the encoder about the new target bit rate.
-  //
-  //          - new_bitrate_kbit : New target bit rate
-  //          - frame_rate       : The target frame rate
-  //
-  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate);
 
  private:
@@ -150,61 +97,20 @@
 
   virtual ~VP8DecoderImpl();
 
-  // Initialize the decoder.
-  //
-  // Return value         :  WEBRTC_VIDEO_CODEC_OK.
-  //                        <0 - Errors:
-  //                                  WEBRTC_VIDEO_CODEC_ERROR
   virtual int InitDecode(const VideoCodec* inst, int number_of_cores);
 
-  // Decode encoded image (as a part of a video stream). The decoded image
-  // will be returned to the user through the decode complete callback.
-  //
-  // Input:
-  //          - input_image         : Encoded image to be decoded
-  //          - missing_frames      : True if one or more frames have been lost
-  //                                  since the previous decode call.
-  //          - fragmentation       : Specifies the start and length of each VP8
-  //                                  partition.
-  //          - codec_specific_info : pointer to specific codec data
-  //          - render_time_ms      : Render time in Ms
-  //
-  // Return value                 : WEBRTC_VIDEO_CODEC_OK if OK
-  //                                <0 - Errors:
-  //                                      WEBRTC_VIDEO_CODEC_ERROR
-  //                                      WEBRTC_VIDEO_CODEC_ERR_PARAMETER
   virtual int Decode(const EncodedImage& input_image,
                      bool missing_frames,
                      const RTPFragmentationHeader* fragmentation,
                      const CodecSpecificInfo* codec_specific_info,
                      int64_t /*render_time_ms*/);
 
-  // Register a decode complete callback object.
-  //
-  // Input:
-  //          - callback         : Callback object which handles decoded images.
-  //
-  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int RegisterDecodeCompleteCallback(DecodedImageCallback* callback);
 
-  // Free decoder memory.
-  //
-  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK
-  //                               <0 - Errors:
-  //                                      WEBRTC_VIDEO_CODEC_ERROR
   virtual int Release();
 
-  // Reset decoder state and prepare for a new call.
-  //
-  // Return value         : WEBRTC_VIDEO_CODEC_OK.
-  //                        <0 - Errors:
-  //                                  WEBRTC_VIDEO_CODEC_UNINITIALIZED
-  //                                  WEBRTC_VIDEO_CODEC_ERROR
   virtual int Reset();
 
-  // Create a copy of the codec and its internal state.
-  //
-  // Return value                : A copy of the instance if OK, NULL otherwise.
   virtual VideoDecoder* Copy();
 
  private:
diff --git a/webrtc/modules/video_coding/codecs/vp9/include/vp9.h b/webrtc/modules/video_coding/codecs/vp9/include/vp9.h
new file mode 100644
index 0000000..cd77f72
--- /dev/null
+++ b/webrtc/modules/video_coding/codecs/vp9/include/vp9.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_H_
+#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_H_
+
+#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
+
+namespace webrtc {
+
+class VP9Encoder : public VideoEncoder {
+ public:
+  static VP9Encoder* Create();
+
+  virtual ~VP9Encoder() {}
+};
+
+
+class VP9Decoder : public VideoDecoder {
+ public:
+  static VP9Decoder* Create();
+
+  virtual ~VP9Decoder() {}
+};
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_INCLUDE_VP9_H_
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9.gyp b/webrtc/modules/video_coding/codecs/vp9/vp9.gyp
new file mode 100644
index 0000000..2bd46fe
--- /dev/null
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9.gyp
@@ -0,0 +1,36 @@
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS.  All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+{
+  'includes': [
+    '../../../../build/common.gypi',
+  ],
+  'targets': [
+    {
+      'target_name': 'webrtc_vp9',
+      'type': 'static_library',
+      'dependencies': [
+        '<(webrtc_root)/common_video/common_video.gyp:common_video',
+        '<(webrtc_root)/modules/video_coding/utility/video_coding_utility.gyp:video_coding_utility',
+        '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
+      ],
+      'conditions': [
+        ['build_libvpx==1', {
+          'dependencies': [
+            '<(DEPTH)/third_party/libvpx/libvpx.gyp:libvpx',
+          ],
+        }],
+      ],
+      'sources': [
+        'include/vp9.h',
+        'vp9_impl.cc',
+        'vp9_impl.h',
+      ],
+    },
+  ],
+}
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
new file mode 100644
index 0000000..33f11a3
--- /dev/null
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -0,0 +1,487 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ */
+
+#include "webrtc/modules/video_coding/codecs/vp9/vp9_impl.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <vector>
+
+#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_decoder.h"
+#include "vpx/vp8cx.h"
+#include "vpx/vp8dx.h"
+
+#include "webrtc/common.h"
+#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
+#include "webrtc/modules/interface/module_common_types.h"
+#include "webrtc/system_wrappers/interface/tick_util.h"
+#include "webrtc/system_wrappers/interface/trace_event.h"
+
+namespace webrtc {
+
+VP9Encoder* VP9Encoder::Create() {
+  return new VP9EncoderImpl();
+}
+
+VP9EncoderImpl::VP9EncoderImpl()
+    : encoded_image_(),
+      encoded_complete_callback_(NULL),
+      inited_(false),
+      timestamp_(0),
+      picture_id_(0),
+      cpu_speed_(3),
+      rc_max_intra_target_(0),
+      encoder_(NULL),
+      config_(NULL),
+      raw_(NULL) {
+  memset(&codec_, 0, sizeof(codec_));
+  uint32_t seed = static_cast<uint32_t>(TickTime::MillisecondTimestamp());
+  srand(seed);
+}
+
+VP9EncoderImpl::~VP9EncoderImpl() {
+  Release();
+}
+
+int VP9EncoderImpl::Release() {
+  if (encoded_image_._buffer != NULL) {
+    delete [] encoded_image_._buffer;
+    encoded_image_._buffer = NULL;
+  }
+  if (encoder_ != NULL) {
+    if (vpx_codec_destroy(encoder_)) {
+      return WEBRTC_VIDEO_CODEC_MEMORY;
+    }
+    delete encoder_;
+    encoder_ = NULL;
+  }
+  if (config_ != NULL) {
+    delete config_;
+    config_ = NULL;
+  }
+  if (raw_ != NULL) {
+    vpx_img_free(raw_);
+    raw_ = NULL;
+  }
+  inited_ = false;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9EncoderImpl::SetRates(uint32_t new_bitrate_kbit,
+                             uint32_t new_framerate) {
+  if (!inited_) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  if (encoder_->err) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+  if (new_framerate < 1) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  // Update bit rate
+  if (codec_.maxBitrate > 0 && new_bitrate_kbit > codec_.maxBitrate) {
+    new_bitrate_kbit = codec_.maxBitrate;
+  }
+  config_->rc_target_bitrate = new_bitrate_kbit;
+  codec_.maxFramerate = new_framerate;
+  // Update encoder context
+  if (vpx_codec_enc_config_set(encoder_, config_)) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9EncoderImpl::InitEncode(const VideoCodec* inst,
+                               int number_of_cores,
+                               uint32_t /*max_payload_size*/) {
+  if (inst == NULL) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  if (inst->maxFramerate < 1) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  // Allow zero to represent an unspecified maxBitRate
+  if (inst->maxBitrate > 0 && inst->startBitrate > inst->maxBitrate) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  if (inst->width < 1 || inst->height < 1) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  if (number_of_cores < 1) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  int retVal = Release();
+  if (retVal < 0) {
+    return retVal;
+  }
+  if (encoder_ == NULL) {
+    encoder_ = new vpx_codec_ctx_t;
+  }
+  if (config_ == NULL) {
+    config_ = new vpx_codec_enc_cfg_t;
+  }
+  timestamp_ = 0;
+  if (&codec_ != inst) {
+    codec_ = *inst;
+  }
+  // Random start 16 bits is enough.
+  picture_id_ = static_cast<uint16_t>(rand()) & 0x7FFF;
+  // Allocate memory for encoded image
+  if (encoded_image_._buffer != NULL) {
+    delete [] encoded_image_._buffer;
+  }
+  encoded_image_._size = CalcBufferSize(kI420, codec_.width, codec_.height);
+  encoded_image_._buffer = new uint8_t[encoded_image_._size];
+  encoded_image_._completeFrame = true;
+  // Creating a wrapper to the image - setting image data to NULL. Actual
+  // pointer will be set in encode. Setting align to 1, as it is meaningless
+  // (actual memory is not allocated).
+  raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height,
+                      1, NULL);
+  // Populate encoder configuration with default values.
+  if (vpx_codec_enc_config_default(vpx_codec_vp9_cx(), config_, 0)) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+  config_->g_w = codec_.width;
+  config_->g_h = codec_.height;
+  config_->rc_target_bitrate = inst->startBitrate;  // in kbit/s
+  config_->g_error_resilient = 1;
+  // Setting the time base of the codec.
+  config_->g_timebase.num = 1;
+  config_->g_timebase.den = 90000;
+  config_->g_lag_in_frames = 0;  // 0- no frame lagging
+  config_->g_threads = 1;
+  // Rate control settings.
+  config_->rc_dropframe_thresh = inst->codecSpecific.VP9.frameDroppingOn ?
+      30 : 0;
+  config_->rc_end_usage = VPX_CBR;
+  config_->g_pass = VPX_RC_ONE_PASS;
+  config_->rc_min_quantizer = 2;
+  config_->rc_max_quantizer = 56;
+  config_->rc_undershoot_pct = 50;
+  config_->rc_overshoot_pct = 50;
+  config_->rc_buf_initial_sz = 500;
+  config_->rc_buf_optimal_sz = 600;
+  config_->rc_buf_sz = 1000;
+  // Set the maximum target size of any key-frame.
+  rc_max_intra_target_ = MaxIntraTarget(config_->rc_buf_optimal_sz);
+  if (inst->codecSpecific.VP9.keyFrameInterval  > 0) {
+    config_->kf_mode = VPX_KF_AUTO;
+    config_->kf_max_dist = inst->codecSpecific.VP9.keyFrameInterval;
+  } else {
+    config_->kf_mode = VPX_KF_DISABLED;
+  }
+  return InitAndSetControlSettings(inst);
+}
+
+int VP9EncoderImpl::InitAndSetControlSettings(const VideoCodec* inst) {
+  if (vpx_codec_enc_init(encoder_, vpx_codec_vp9_cx(), config_, 0)) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  // Only positive speeds, currently: 0 - 7.
+  // O means slowest/best quality, 7 means fastest/lowest quality.
+  // TODO(marpan): Speeds 5-7 are speed settings for real-time mode, on desktop.
+  // Currently set to 5, update to 6 (for faster encoding) after some subjective
+  // quality tests.
+  cpu_speed_ = 5;
+  // Note: some of these codec controls still use "VP8" in the control name.
+  // TODO(marpan): Update this in the next/future libvpx version.
+  vpx_codec_control(encoder_, VP8E_SET_CPUUSED, cpu_speed_);
+  vpx_codec_control(encoder_, VP8E_SET_MAX_INTRA_BITRATE_PCT,
+                    rc_max_intra_target_);
+  vpx_codec_control(encoder_, VP9E_SET_AQ_MODE,
+                    inst->codecSpecific.VP9.adaptiveQpMode ? 3 : 0);
+  // TODO(marpan): Enable in future libvpx roll: waiting for SSE2 optimization.
+// #if !defined(WEBRTC_ARCH_ARM)
+  // vpx_codec_control(encoder_, VP9E_SET_NOISE_SENSITIVITY,
+  //                   inst->codecSpecific.VP9.denoisingOn ? 1 : 0);
+// #endif
+  inited_ = true;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+uint32_t VP9EncoderImpl::MaxIntraTarget(uint32_t optimal_buffer_size) {
+  // Set max to the optimal buffer level (normalized by target BR),
+  // and scaled by a scale_par.
+  // Max target size = scale_par * optimal_buffer_size * targetBR[Kbps].
+  // This value is presented in percentage of perFrameBw:
+  // perFrameBw = targetBR[Kbps] * 1000 / framerate.
+  // The target in % is as follows:
+  float scale_par = 0.5;
+  uint32_t target_pct =
+      optimal_buffer_size * scale_par * codec_.maxFramerate / 10;
+  // Don't go below 3 times the per frame bandwidth.
+  const uint32_t min_intra_size = 300;
+  return (target_pct < min_intra_size) ? min_intra_size: target_pct;
+}
+
+int VP9EncoderImpl::Encode(const I420VideoFrame& input_image,
+                           const CodecSpecificInfo* codec_specific_info,
+                           const std::vector<VideoFrameType>* frame_types) {
+  if (!inited_) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  if (input_image.IsZeroSize()) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  if (encoded_complete_callback_ == NULL) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  VideoFrameType frame_type = kDeltaFrame;
+  // We only support one stream at the moment.
+  if (frame_types && frame_types->size() > 0) {
+    frame_type = (*frame_types)[0];
+  }
+  // Image in vpx_image_t format.
+  // Input image is const. VPX's raw image is not defined as const.
+  raw_->planes[VPX_PLANE_Y] = const_cast<uint8_t*>(input_image.buffer(kYPlane));
+  raw_->planes[VPX_PLANE_U] = const_cast<uint8_t*>(input_image.buffer(kUPlane));
+  raw_->planes[VPX_PLANE_V] = const_cast<uint8_t*>(input_image.buffer(kVPlane));
+  raw_->stride[VPX_PLANE_Y] = input_image.stride(kYPlane);
+  raw_->stride[VPX_PLANE_U] = input_image.stride(kUPlane);
+  raw_->stride[VPX_PLANE_V] = input_image.stride(kVPlane);
+
+  int flags = 0;
+  bool send_keyframe = (frame_type == kKeyFrame);
+  if (send_keyframe) {
+    // Key frame request from caller.
+    flags = VPX_EFLAG_FORCE_KF;
+  }
+  assert(codec_.maxFramerate > 0);
+  uint32_t duration = 90000 / codec_.maxFramerate;
+  if (vpx_codec_encode(encoder_, raw_, timestamp_, duration, flags,
+                       VPX_DL_REALTIME)) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+  timestamp_ += duration;
+  return GetEncodedPartitions(input_image);
+}
+
+void VP9EncoderImpl::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
+                                       const vpx_codec_cx_pkt& pkt,
+                                       uint32_t timestamp) {
+  assert(codec_specific != NULL);
+  codec_specific->codecType = kVideoCodecVP9;
+  CodecSpecificInfoVP9 *vp9_info = &(codec_specific->codecSpecific.VP9);
+  vp9_info->pictureId = picture_id_;
+  vp9_info->keyIdx = kNoKeyIdx;
+  vp9_info->nonReference = (pkt.data.frame.flags & VPX_FRAME_IS_DROPPABLE) != 0;
+  // TODO(marpan): Temporal layers are supported in the current VP9 version,
+  // but for now use 1 temporal layer encoding. Will update this when temporal
+  // layer support for VP9 is added in webrtc.
+  vp9_info->temporalIdx = kNoTemporalIdx;
+  vp9_info->layerSync = false;
+  vp9_info->tl0PicIdx = kNoTl0PicIdx;
+  picture_id_ = (picture_id_ + 1) & 0x7FFF;
+}
+
+int VP9EncoderImpl::GetEncodedPartitions(const I420VideoFrame& input_image) {
+  vpx_codec_iter_t iter = NULL;
+  encoded_image_._length = 0;
+  encoded_image_._frameType = kDeltaFrame;
+  RTPFragmentationHeader frag_info;
+  // Note: no data partitioning in VP9, so 1 partition only. We keep this
+  // fragmentation data for now, until VP9 packetizer is implemented.
+  frag_info.VerifyAndAllocateFragmentationHeader(1);
+  int part_idx = 0;
+  CodecSpecificInfo codec_specific;
+  const vpx_codec_cx_pkt_t *pkt = NULL;
+  while ((pkt = vpx_codec_get_cx_data(encoder_, &iter)) != NULL) {
+    switch (pkt->kind) {
+      case VPX_CODEC_CX_FRAME_PKT: {
+        memcpy(&encoded_image_._buffer[encoded_image_._length],
+               pkt->data.frame.buf,
+               pkt->data.frame.sz);
+        frag_info.fragmentationOffset[part_idx] = encoded_image_._length;
+        frag_info.fragmentationLength[part_idx] =
+            static_cast<uint32_t>(pkt->data.frame.sz);
+        frag_info.fragmentationPlType[part_idx] = 0;
+        frag_info.fragmentationTimeDiff[part_idx] = 0;
+        encoded_image_._length += static_cast<uint32_t>(pkt->data.frame.sz);
+        assert(encoded_image_._length <= encoded_image_._size);
+        break;
+      }
+      default: {
+        break;
+      }
+    }
+    // End of frame.
+    if ((pkt->data.frame.flags & VPX_FRAME_IS_FRAGMENT) == 0) {
+      // Check if encoded frame is a key frame.
+      if (pkt->data.frame.flags & VPX_FRAME_IS_KEY) {
+        encoded_image_._frameType = kKeyFrame;
+      }
+      PopulateCodecSpecific(&codec_specific, *pkt, input_image.timestamp());
+      break;
+    }
+  }
+  if (encoded_image_._length > 0) {
+    TRACE_COUNTER1("webrtc", "EncodedFrameSize", encoded_image_._length);
+    encoded_image_._timeStamp = input_image.timestamp();
+    encoded_image_.capture_time_ms_ = input_image.render_time_ms();
+    encoded_image_._encodedHeight = raw_->d_h;
+    encoded_image_._encodedWidth = raw_->d_w;
+    encoded_complete_callback_->Encoded(encoded_image_, &codec_specific,
+                                      &frag_info);
+  }
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9EncoderImpl::SetChannelParameters(uint32_t packet_loss, int rtt) {
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9EncoderImpl::RegisterEncodeCompleteCallback(
+    EncodedImageCallback* callback) {
+  encoded_complete_callback_ = callback;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+VP9Decoder* VP9Decoder::Create() {
+  return new VP9DecoderImpl();
+}
+
+VP9DecoderImpl::VP9DecoderImpl()
+    : decode_complete_callback_(NULL),
+      inited_(false),
+      decoder_(NULL),
+      key_frame_required_(true) {
+  memset(&codec_, 0, sizeof(codec_));
+}
+
+VP9DecoderImpl::~VP9DecoderImpl() {
+  inited_ = true;  // in order to do the actual release
+  Release();
+}
+
+int VP9DecoderImpl::Reset() {
+  if (!inited_) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  InitDecode(&codec_, 1);
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9DecoderImpl::InitDecode(const VideoCodec* inst, int number_of_cores) {
+  if (inst == NULL) {
+    return WEBRTC_VIDEO_CODEC_ERR_PARAMETER;
+  }
+  int ret_val = Release();
+  if (ret_val < 0) {
+    return ret_val;
+  }
+  if (decoder_ == NULL) {
+    decoder_ = new vpx_dec_ctx_t;
+  }
+  vpx_codec_dec_cfg_t  cfg;
+  // Setting number of threads to a constant value (1)
+  cfg.threads = 1;
+  cfg.h = cfg.w = 0;  // set after decode
+  vpx_codec_flags_t flags = 0;
+  if (vpx_codec_dec_init(decoder_, vpx_codec_vp9_dx(), &cfg, flags)) {
+    return WEBRTC_VIDEO_CODEC_MEMORY;
+  }
+  if (&codec_ != inst) {
+    // Save VideoCodec instance for later; mainly for duplicating the decoder.
+    codec_ = *inst;
+  }
+  inited_ = true;
+  // Always start with a complete key frame.
+  key_frame_required_ = true;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9DecoderImpl::Decode(const EncodedImage& input_image,
+                           bool missing_frames,
+                           const RTPFragmentationHeader* fragmentation,
+                           const CodecSpecificInfo* codec_specific_info,
+                           int64_t /*render_time_ms*/) {
+  if (!inited_) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  if (decode_complete_callback_ == NULL) {
+    return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+  }
+  // Always start with a complete key frame.
+  if (key_frame_required_) {
+    if (input_image._frameType != kKeyFrame)
+      return WEBRTC_VIDEO_CODEC_ERROR;
+    // We have a key frame - is it complete?
+    if (input_image._completeFrame) {
+      key_frame_required_ = false;
+    } else {
+      return WEBRTC_VIDEO_CODEC_ERROR;
+    }
+  }
+  vpx_codec_iter_t iter = NULL;
+  vpx_image_t* img;
+  uint8_t* buffer = input_image._buffer;
+  if (input_image._length == 0) {
+    buffer = NULL;  // Triggers full frame concealment.
+  }
+  if (vpx_codec_decode(decoder_,
+                       buffer,
+                       input_image._length,
+                       0,
+                       VPX_DL_REALTIME)) {
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+  img = vpx_codec_get_frame(decoder_, &iter);
+  int ret = ReturnFrame(img, input_image._timeStamp);
+  if (ret != 0) {
+    return ret;
+  }
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9DecoderImpl::ReturnFrame(const vpx_image_t* img, uint32_t timestamp) {
+  if (img == NULL) {
+    // Decoder OK and NULL image => No show frame.
+    return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
+  }
+  int half_height = (img->d_h + 1) / 2;
+  int size_y = img->stride[VPX_PLANE_Y] * img->d_h;
+  int size_u = img->stride[VPX_PLANE_U] * half_height;
+  int size_v = img->stride[VPX_PLANE_V] * half_height;
+  decoded_image_.CreateFrame(size_y, img->planes[VPX_PLANE_Y],
+                             size_u, img->planes[VPX_PLANE_U],
+                             size_v, img->planes[VPX_PLANE_V],
+                             img->d_w, img->d_h,
+                             img->stride[VPX_PLANE_Y],
+                             img->stride[VPX_PLANE_U],
+                             img->stride[VPX_PLANE_V]);
+  decoded_image_.set_timestamp(timestamp);
+  int ret = decode_complete_callback_->Decoded(decoded_image_);
+  if (ret != 0)
+    return ret;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9DecoderImpl::RegisterDecodeCompleteCallback(
+    DecodedImageCallback* callback) {
+  decode_complete_callback_ = callback;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int VP9DecoderImpl::Release() {
+  if (decoder_ != NULL) {
+    if (vpx_codec_destroy(decoder_)) {
+      return WEBRTC_VIDEO_CODEC_MEMORY;
+    }
+    delete decoder_;
+    decoder_ = NULL;
+  }
+  inited_ = false;
+  return WEBRTC_VIDEO_CODEC_OK;
+}
+}  // namespace webrtc
diff --git a/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
new file mode 100644
index 0000000..94788db
--- /dev/null
+++ b/webrtc/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -0,0 +1,115 @@
+/*
+ *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ *
+ */
+
+#ifndef WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_IMPL_H_
+#define WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_IMPL_H_
+
+#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
+
+// VPX forward declaration
+typedef struct vpx_codec_ctx vpx_codec_ctx_t;
+typedef struct vpx_codec_ctx vpx_dec_ctx_t;
+typedef struct vpx_codec_enc_cfg vpx_codec_enc_cfg_t;
+typedef struct vpx_image vpx_image_t;
+typedef struct vpx_ref_frame vpx_ref_frame_t;
+struct vpx_codec_cx_pkt;
+
+namespace webrtc {
+
+class VP9EncoderImpl : public VP9Encoder {
+ public:
+  VP9EncoderImpl();
+
+  virtual ~VP9EncoderImpl();
+
+  virtual int Release() OVERRIDE;
+
+  virtual int InitEncode(const VideoCodec* codec_settings,
+                         int number_of_cores,
+                         uint32_t max_payload_size) OVERRIDE;
+
+  virtual int Encode(const I420VideoFrame& input_image,
+                     const CodecSpecificInfo* codec_specific_info,
+                     const std::vector<VideoFrameType>* frame_types) OVERRIDE;
+
+  virtual int RegisterEncodeCompleteCallback(EncodedImageCallback* callback)
+  OVERRIDE;
+
+  virtual int SetChannelParameters(uint32_t packet_loss, int rtt) OVERRIDE;
+
+  virtual int SetRates(uint32_t new_bitrate_kbit, uint32_t frame_rate) OVERRIDE;
+
+ private:
+  // Call encoder initialize function and set control settings.
+  int InitAndSetControlSettings(const VideoCodec* inst);
+
+  void PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
+                             const vpx_codec_cx_pkt& pkt,
+                             uint32_t timestamp);
+
+  int GetEncodedPartitions(const I420VideoFrame& input_image);
+
+  // Determine maximum target for Intra frames
+  //
+  // Input:
+  //    - optimal_buffer_size : Optimal buffer size
+  // Return Value             : Max target size for Intra frames represented as
+  //                            percentage of the per frame bandwidth
+  uint32_t MaxIntraTarget(uint32_t optimal_buffer_size);
+
+  EncodedImage encoded_image_;
+  EncodedImageCallback* encoded_complete_callback_;
+  VideoCodec codec_;
+  bool inited_;
+  int64_t timestamp_;
+  uint16_t picture_id_;
+  int cpu_speed_;
+  uint32_t rc_max_intra_target_;
+  vpx_codec_ctx_t* encoder_;
+  vpx_codec_enc_cfg_t* config_;
+  vpx_image_t* raw_;
+};
+
+
+class VP9DecoderImpl : public VP9Decoder {
+ public:
+  VP9DecoderImpl();
+
+  virtual ~VP9DecoderImpl();
+
+  virtual int InitDecode(const VideoCodec* inst, int number_of_cores) OVERRIDE;
+
+  virtual int Decode(const EncodedImage& input_image,
+                     bool missing_frames,
+                     const RTPFragmentationHeader* fragmentation,
+                     const CodecSpecificInfo* codec_specific_info,
+                     int64_t /*render_time_ms*/) OVERRIDE;
+
+  virtual int RegisterDecodeCompleteCallback(DecodedImageCallback* callback)
+  OVERRIDE;
+
+  virtual int Release() OVERRIDE;
+
+  virtual int Reset() OVERRIDE;
+
+ private:
+  int ReturnFrame(const vpx_image_t* img, uint32_t timeStamp);
+
+  I420VideoFrame decoded_image_;
+  DecodedImageCallback* decode_complete_callback_;
+  bool inited_;
+  vpx_dec_ctx_t* decoder_;
+  VideoCodec codec_;
+  bool key_frame_required_;
+};
+}  // namespace webrtc
+
+#endif  // WEBRTC_MODULES_VIDEO_CODING_CODECS_VP9_IMPL_H_
diff --git a/webrtc/modules/video_coding/main/interface/video_coding_defines.h b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
index 0919c892..efdc41b 100644
--- a/webrtc/modules/video_coding/main/interface/video_coding_defines.h
+++ b/webrtc/modules/video_coding/main/interface/video_coding_defines.h
@@ -39,6 +39,7 @@
 #define VCM_RED_PAYLOAD_TYPE        96
 #define VCM_ULPFEC_PAYLOAD_TYPE     97
 #define VCM_VP8_PAYLOAD_TYPE       100
+#define VCM_VP9_PAYLOAD_TYPE       101
 #define VCM_I420_PAYLOAD_TYPE      124
 #define VCM_H264_PAYLOAD_TYPE      127
 
diff --git a/webrtc/modules/video_coding/main/source/codec_database.cc b/webrtc/modules/video_coding/main/source/codec_database.cc
index e99cc52..2fc9246 100644
--- a/webrtc/modules/video_coding/main/source/codec_database.cc
+++ b/webrtc/modules/video_coding/main/source/codec_database.cc
@@ -19,6 +19,9 @@
 #ifdef VIDEOCODEC_VP8
 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
 #endif
+#ifdef VIDEOCODEC_VP9
+#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
+#endif
 #include "webrtc/modules/video_coding/main/source/internal_defines.h"
 #include "webrtc/system_wrappers/interface/logging.h"
 
@@ -39,6 +42,20 @@
   return vp8_settings;
 }
 
+VideoCodecVP9 VideoEncoder::GetDefaultVp9Settings() {
+  VideoCodecVP9 vp9_settings;
+  memset(&vp9_settings, 0, sizeof(vp9_settings));
+
+  vp9_settings.resilience = 1;
+  vp9_settings.numberOfTemporalLayers = 1;
+  vp9_settings.denoisingOn = false;
+  vp9_settings.frameDroppingOn = true;
+  vp9_settings.keyFrameInterval = 3000;
+  vp9_settings.adaptiveQpMode = true;
+
+  return vp9_settings;
+}
+
 VideoCodecH264 VideoEncoder::GetDefaultH264Settings() {
   VideoCodecH264 h264_settings;
   memset(&h264_settings, 0, sizeof(h264_settings));
@@ -126,6 +143,24 @@
       return true;
     }
 #endif
+#ifdef VIDEOCODEC_VP9
+    case VCM_VP9_IDX: {
+      strncpy(settings->plName, "VP9", 4);
+      settings->codecType = kVideoCodecVP9;
+      // 96 to 127 dynamic payload types for video codecs.
+      settings->plType = VCM_VP9_PAYLOAD_TYPE;
+      settings->startBitrate = 100;
+      settings->minBitrate = VCM_MIN_BITRATE;
+      settings->maxBitrate = 0;
+      settings->maxFramerate = VCM_DEFAULT_FRAME_RATE;
+      settings->width = VCM_DEFAULT_CODEC_WIDTH;
+      settings->height = VCM_DEFAULT_CODEC_HEIGHT;
+      settings->numberOfSimulcastStreams = 0;
+      settings->qpMax = 56;
+      settings->codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
+      return true;
+    }
+#endif
 #ifdef VIDEOCODEC_H264
     case VCM_H264_IDX: {
       strncpy(settings->plName, "H264", 5);
@@ -362,6 +397,13 @@
         return true;
       }
       break;
+    case kVideoCodecVP9:
+      if (memcmp(&new_send_codec.codecSpecific.VP9,
+                 &send_codec_.codecSpecific.VP9,
+                 sizeof(new_send_codec.codecSpecific.VP9)) != 0) {
+        return true;
+      }
+      break;
     case kVideoCodecH264:
       if (memcmp(&new_send_codec.codecSpecific.H264,
                  &send_codec_.codecSpecific.H264,
@@ -635,6 +677,10 @@
     case kVideoCodecVP8:
       return new VCMGenericEncoder(*(VP8Encoder::Create()));
 #endif
+#ifdef VIDEOCODEC_VP9
+    case kVideoCodecVP9:
+      return new VCMGenericEncoder(*(VP9Encoder::Create()));
+#endif
 #ifdef VIDEOCODEC_I420
     case kVideoCodecI420:
       return new VCMGenericEncoder(*(new I420Encoder));
@@ -662,6 +708,10 @@
     case kVideoCodecVP8:
       return new VCMGenericDecoder(*(VP8Decoder::Create()));
 #endif
+#ifdef VIDEOCODEC_VP9
+    case kVideoCodecVP9:
+      return new VCMGenericDecoder(*(VP9Decoder::Create()));
+#endif
 #ifdef VIDEOCODEC_I420
     case kVideoCodecI420:
       return new VCMGenericDecoder(*(new I420Decoder));
diff --git a/webrtc/modules/video_coding/main/source/internal_defines.h b/webrtc/modules/video_coding/main/source/internal_defines.h
index ef42c62..adc940f 100644
--- a/webrtc/modules/video_coding/main/source/internal_defines.h
+++ b/webrtc/modules/video_coding/main/source/internal_defines.h
@@ -39,10 +39,15 @@
 #else
   #define VCM_VP8_IDX VCM_NO_CODEC_IDX
 #endif
-#ifdef VIDEOCODEC_H264
-  #define VCM_H264_IDX (VCM_VP8_IDX + 1)
+#ifdef VIDEOCODEC_VP9
+  #define VCM_VP9_IDX (VCM_VP8_IDX + 1)
 #else
-  #define VCM_H264_IDX VCM_VP8_IDX
+  #define VCM_VP9_IDX VCM_VP8_IDX
+#endif
+#ifdef VIDEOCODEC_H264
+  #define VCM_H264_IDX (VCM_VP9_IDX + 1)
+#else
+  #define VCM_H264_IDX VCM_VP9_IDX
 #endif
 #ifdef VIDEOCODEC_I420
   #define VCM_I420_IDX (VCM_H264_IDX + 1)
diff --git a/webrtc/modules/video_coding/main/source/video_coding.gypi b/webrtc/modules/video_coding/main/source/video_coding.gypi
index f19a585..02c5a5c 100644
--- a/webrtc/modules/video_coding/main/source/video_coding.gypi
+++ b/webrtc/modules/video_coding/main/source/video_coding.gypi
@@ -17,6 +17,7 @@
         '<(webrtc_root)/modules/video_coding/utility/video_coding_utility.gyp:video_coding_utility',
         '<(webrtc_root)/system_wrappers/source/system_wrappers.gyp:system_wrappers',
         '<(webrtc_vp8_dir)/vp8.gyp:webrtc_vp8',
+        '<(webrtc_vp9_dir)/vp9.gyp:webrtc_vp9',
       ],
       'sources': [
         # interfaces
diff --git a/webrtc/modules/video_coding/main/test/normal_test.cc b/webrtc/modules/video_coding/main/test/normal_test.cc
index f23682b..815c3ac 100644
--- a/webrtc/modules/video_coding/main/test/normal_test.cc
+++ b/webrtc/modules/video_coding/main/test/normal_test.cc
@@ -101,6 +101,9 @@
     rtpInfo.type.Video.codecHeader.VP8.pictureId =
         videoHdr->codecHeader.VP8.pictureId;
     break;
+  case kVideoCodecVP9:
+    // Leave for now, until we add kRtpVideoVp9 to RTP.
+    break;
   default:
     assert(false);
     return -1;
diff --git a/webrtc/modules/video_coding/main/test/test_callbacks.cc b/webrtc/modules/video_coding/main/test/test_callbacks.cc
index 710a06e..d68f994 100644
--- a/webrtc/modules/video_coding/main/test/test_callbacks.cc
+++ b/webrtc/modules/video_coding/main/test/test_callbacks.cc
@@ -82,6 +82,9 @@
         rtpInfo.type.Video.codecHeader.VP8.pictureId =
             videoHdr->codecHeader.VP8.pictureId;
         break;
+    case webrtc::kRtpVideoGeneric:
+      // Leave for now, until we add kRtpVideoVp9 to RTP.
+      break;
     default:
         assert(false);
         return -1;
diff --git a/webrtc/modules/video_coding/main/test/test_util.cc b/webrtc/modules/video_coding/main/test/test_util.cc
index 09ad991..d2b8f8c 100644
--- a/webrtc/modules/video_coding/main/test/test_util.cc
+++ b/webrtc/modules/video_coding/main/test/test_util.cc
@@ -151,6 +151,7 @@
   if (strncmp(plname,"VP8" , 3) == 0) {
     return webrtc::kRtpVideoVp8;
   } else {
-    return webrtc::kRtpVideoNone;  // Default value
+    // Default value.
+    return webrtc::kRtpVideoGeneric;
   }
 }
diff --git a/webrtc/modules/video_coding/main/test/tester_main.cc b/webrtc/modules/video_coding/main/test/tester_main.cc
index bf17ab2..874fa9e 100644
--- a/webrtc/modules/video_coding/main/test/tester_main.cc
+++ b/webrtc/modules/video_coding/main/test/tester_main.cc
@@ -63,6 +63,8 @@
   args.codecName = FLAGS_codec;
   if (args.codecName == "VP8") {
     args.codecType = kVideoCodecVP8;
+  } else if (args.codecName == "VP9") {
+    args.codecType = kVideoCodecVP9;
   } else if (args.codecName == "I420") {
     args.codecType = kVideoCodecI420;
   } else {
diff --git a/webrtc/video/call.cc b/webrtc/video/call.cc
index ff70fda..fd41d75 100644
--- a/webrtc/video/call.cc
+++ b/webrtc/video/call.cc
@@ -20,6 +20,7 @@
 #include "webrtc/config.h"
 #include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h"
 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/rw_lock_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
@@ -46,6 +47,8 @@
   switch (codec_type) {
     case kVp8:
       return VP8Encoder::Create();
+    case kVp9:
+      return VP9Encoder::Create();
   }
   assert(false);
   return NULL;
diff --git a/webrtc/video/end_to_end_tests.cc b/webrtc/video/end_to_end_tests.cc
index f9a11e4..06cb187 100644
--- a/webrtc/video/end_to_end_tests.cc
+++ b/webrtc/video/end_to_end_tests.cc
@@ -19,6 +19,9 @@
 #include "webrtc/call.h"
 #include "webrtc/frame_callback.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
+#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 #include "webrtc/system_wrappers/interface/event_wrapper.h"
 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
@@ -222,6 +225,57 @@
   DestroyStreams();
 }
 
+// TODO(marpan): Re-enable this test on the next libvpx roll.
+TEST_F(EndToEndTest, DISABLED_SendsAndReceivesVP9) {
+  class VP9Observer : public test::EndToEndTest, public VideoRenderer {
+   public:
+    VP9Observer()
+        : EndToEndTest(2 * kDefaultTimeoutMs),
+          encoder_(VideoEncoder::Create(VideoEncoder::kVp9)),
+          decoder_(VP9Decoder::Create()),
+          frame_counter_(0) {}
+
+    virtual void PerformTest() OVERRIDE {
+      EXPECT_EQ(kEventSignaled, Wait())
+          << "Timed out while waiting for enough frames to be decoded.";
+    }
+
+    virtual void ModifyConfigs(
+        VideoSendStream::Config* send_config,
+        std::vector<VideoReceiveStream::Config>* receive_configs,
+        VideoEncoderConfig* encoder_config) OVERRIDE {
+      send_config->encoder_settings.encoder = encoder_.get();
+      send_config->encoder_settings.payload_name = "VP9";
+      send_config->encoder_settings.payload_type = VCM_VP9_PAYLOAD_TYPE;
+      encoder_config->streams[0].min_bitrate_bps = 50000;
+      encoder_config->streams[0].target_bitrate_bps =
+          encoder_config->streams[0].max_bitrate_bps = 2000000;
+
+      (*receive_configs)[0].renderer = this;
+      (*receive_configs)[0].decoders.resize(1);
+      (*receive_configs)[0].decoders[0].payload_type =
+          send_config->encoder_settings.payload_type;
+      (*receive_configs)[0].decoders[0].payload_name =
+          send_config->encoder_settings.payload_name;
+      (*receive_configs)[0].decoders[0].decoder = decoder_.get();
+    }
+
+    virtual void RenderFrame(const I420VideoFrame& video_frame,
+                             int time_to_render_ms) OVERRIDE {
+      const int kRequiredFrames = 500;
+      if (++frame_counter_ == kRequiredFrames)
+        observation_complete_->Set();
+    }
+
+   private:
+    scoped_ptr<webrtc::VideoEncoder> encoder_;
+    scoped_ptr<webrtc::VideoDecoder> decoder_;
+    int frame_counter_;
+  } test;
+
+  RunBaseTest(&test);
+}
+
 TEST_F(EndToEndTest, SendsAndReceivesH264) {
   class H264Observer : public test::EndToEndTest, public VideoRenderer {
    public:
diff --git a/webrtc/video/video_send_stream.cc b/webrtc/video/video_send_stream.cc
index d6ebc2b..28231b0 100644
--- a/webrtc/video/video_send_stream.cc
+++ b/webrtc/video/video_send_stream.cc
@@ -301,6 +301,8 @@
   memset(&video_codec, 0, sizeof(video_codec));
   if (config_.encoder_settings.payload_name == "VP8") {
     video_codec.codecType = kVideoCodecVP8;
+  } else if (config_.encoder_settings.payload_name == "VP9") {
+    video_codec.codecType = kVideoCodecVP9;
   } else if (config_.encoder_settings.payload_name == "H264") {
     video_codec.codecType = kVideoCodecH264;
   } else {
@@ -323,6 +325,8 @@
 
   if (video_codec.codecType == kVideoCodecVP8) {
     video_codec.codecSpecific.VP8 = VideoEncoder::GetDefaultVp8Settings();
+  } else if (video_codec.codecType == kVideoCodecVP9) {
+    video_codec.codecSpecific.VP9 = VideoEncoder::GetDefaultVp9Settings();
   } else if (video_codec.codecType == kVideoCodecH264) {
     video_codec.codecSpecific.H264 = VideoEncoder::GetDefaultH264Settings();
   }
diff --git a/webrtc/video_encoder.h b/webrtc/video_encoder.h
index cbdf1ef..2bf52f3 100644
--- a/webrtc/video_encoder.h
+++ b/webrtc/video_encoder.h
@@ -40,28 +40,84 @@
  public:
   enum EncoderType {
     kVp8,
+    kVp9,
   };
 
   static VideoEncoder* Create(EncoderType codec_type);
 
   static VideoCodecVP8 GetDefaultVp8Settings();
+  static VideoCodecVP9 GetDefaultVp9Settings();
   static VideoCodecH264 GetDefaultH264Settings();
 
   virtual ~VideoEncoder() {}
 
+  // Initialize the encoder with the information from the codecSettings
+  //
+  // Input:
+  //          - codec_settings    : Codec settings
+  //          - number_of_cores   : Number of cores available for the encoder
+  //          - max_payload_size  : The maximum size each payload is allowed
+  //                                to have. Usually MTU - overhead.
+  //
+  // Return value                  : Set bit rate if OK
+  //                                 <0 - Errors:
+  //                                  WEBRTC_VIDEO_CODEC_ERR_PARAMETER
+  //                                  WEBRTC_VIDEO_CODEC_ERR_SIZE
+  //                                  WEBRTC_VIDEO_CODEC_LEVEL_EXCEEDED
+  //                                  WEBRTC_VIDEO_CODEC_MEMORY
+  //                                  WEBRTC_VIDEO_CODEC_ERROR
   virtual int32_t InitEncode(const VideoCodec* codec_settings,
                              int32_t number_of_cores,
                              uint32_t max_payload_size) = 0;
+
+  // Register an encode complete callback object.
+  //
+  // Input:
+  //          - callback         : Callback object which handles encoded images.
+  //
+  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int32_t RegisterEncodeCompleteCallback(
       EncodedImageCallback* callback) = 0;
+
+  // Free encoder memory.
+  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int32_t Release() = 0;
 
-
+  // Encode an I420 image (as a part of a video stream). The encoded image
+  // will be returned to the user through the encode complete callback.
+  //
+  // Input:
+  //          - frame             : Image to be encoded
+  //          - frame_types       : Frame type to be generated by the encoder.
+  //
+  // Return value                 : WEBRTC_VIDEO_CODEC_OK if OK
+  //                                <0 - Errors:
+  //                                  WEBRTC_VIDEO_CODEC_ERR_PARAMETER
+  //                                  WEBRTC_VIDEO_CODEC_MEMORY
+  //                                  WEBRTC_VIDEO_CODEC_ERROR
+  //                                  WEBRTC_VIDEO_CODEC_TIMEOUT
   virtual int32_t Encode(const I420VideoFrame& frame,
                          const CodecSpecificInfo* codec_specific_info,
                          const std::vector<VideoFrameType>* frame_types) = 0;
 
+  // Inform the encoder of the new packet loss rate and the round-trip time of
+  // the network.
+  //
+  // Input:
+  //          - packet_loss : Fraction lost
+  //                          (loss rate in percent = 100 * packetLoss / 255)
+  //          - rtt         : Round-trip time in milliseconds
+  // Return value           : WEBRTC_VIDEO_CODEC_OK if OK
+  //                          <0 - Errors: WEBRTC_VIDEO_CODEC_ERROR
   virtual int32_t SetChannelParameters(uint32_t packet_loss, int rtt) = 0;
+
+  // Inform the encoder about the new target bit rate.
+  //
+  // Input:
+  //          - bitrate         : New target bit rate
+  //          - framerate       : The target frame rate
+  //
+  // Return value                : WEBRTC_VIDEO_CODEC_OK if OK, < 0 otherwise.
   virtual int32_t SetRates(uint32_t bitrate, uint32_t framerate) = 0;
 
   virtual int32_t SetPeriodicKeyFrames(bool enable) { return -1; }
diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
index fb1a46f..41fafae 100644
--- a/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
+++ b/webrtc/video_engine/test/auto_test/source/vie_autotest.cc
@@ -98,6 +98,9 @@
         case webrtc::kVideoCodecVP8:
             ViETest::Log("\tcodecType: VP8");
             break;
+        case webrtc::kVideoCodecVP9:
+            ViETest::Log("\tcodecType: VP9");
+            break;
         case webrtc::kVideoCodecI420:
             ViETest::Log("\tcodecType: I420");
             break;
diff --git a/webrtc/video_engine/vie_codec_impl.cc b/webrtc/video_engine/vie_codec_impl.cc
index f939a66..0ef039d 100644
--- a/webrtc/video_engine/vie_codec_impl.cc
+++ b/webrtc/video_engine/vie_codec_impl.cc
@@ -640,6 +640,8 @@
     return false;
   } else if ((video_codec.codecType == kVideoCodecVP8 &&
               strncmp(video_codec.plName, "VP8", 4) == 0) ||
+             (video_codec.codecType == kVideoCodecVP9 &&
+              strncmp(video_codec.plName, "VP9", 4) == 0) ||
              (video_codec.codecType == kVideoCodecI420 &&
               strncmp(video_codec.plName, "I420", 4) == 0) ||
              (video_codec.codecType == kVideoCodecH264 &&
diff --git a/webrtc/webrtc.gyp b/webrtc/webrtc.gyp
index 2b24deb..f9ed883 100644
--- a/webrtc/webrtc.gyp
+++ b/webrtc/webrtc.gyp
@@ -36,6 +36,7 @@
       'video_engine/video_engine.gyp:*',
       'voice_engine/voice_engine.gyp:*',
       '<(webrtc_vp8_dir)/vp8.gyp:*',
+      '<(webrtc_vp9_dir)/vp9.gyp:*',
     ],
   },
   'targets': [