Use CopyOnWriteBuffer instead of Buffer to avoid unnecessary copies.

This CL removes copy and assign support from Buffer and changes various
parameters from Buffer to CopyOnWriteBuffer so they can be passed along
and copied without actually copying the underlying data.

With this changed some parameters to be "const" and fixed an issue when
creating a CopyOnWriteBuffer with empty data.

BUG=webrtc:5155

Review URL: https://codereview.webrtc.org/1785713005

Cr-Commit-Position: refs/heads/master@{#12058}
diff --git a/talk/app/webrtc/objc/RTCDataChannel.mm b/talk/app/webrtc/objc/RTCDataChannel.mm
index 114b916..6cfa562 100644
--- a/talk/app/webrtc/objc/RTCDataChannel.mm
+++ b/talk/app/webrtc/objc/RTCDataChannel.mm
@@ -153,8 +153,8 @@
 - (instancetype)initWithData:(NSData*)data isBinary:(BOOL)isBinary {
   NSAssert(data, @"data cannot be nil");
   if (self = [super init]) {
-    rtc::Buffer buffer(reinterpret_cast<const uint8_t*>([data bytes]),
-                       [data length]);
+    rtc::CopyOnWriteBuffer buffer(
+        reinterpret_cast<const uint8_t*>([data bytes]), [data length]);
     _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
   }
   return self;
diff --git a/webrtc/api/datachannel.cc b/webrtc/api/datachannel.cc
index b4dc5d8..612d7e0 100644
--- a/webrtc/api/datachannel.cc
+++ b/webrtc/api/datachannel.cc
@@ -324,7 +324,7 @@
 
 void DataChannel::OnDataReceived(cricket::DataChannel* channel,
                                  const cricket::ReceiveDataParams& params,
-                                 const rtc::Buffer& payload) {
+                                 const rtc::CopyOnWriteBuffer& payload) {
   uint32_t expected_ssrc =
       (data_channel_type_ == cricket::DCT_RTP) ? receive_ssrc_ : config_.id;
   if (params.ssrc != expected_ssrc) {
@@ -422,11 +422,11 @@
         }
         if (connected_to_provider_) {
           if (handshake_state_ == kHandshakeShouldSendOpen) {
-            rtc::Buffer payload;
+            rtc::CopyOnWriteBuffer payload;
             WriteDataChannelOpenMessage(label_, config_, &payload);
             SendControlMessage(payload);
           } else if (handshake_state_ == kHandshakeShouldSendAck) {
-            rtc::Buffer payload;
+            rtc::CopyOnWriteBuffer payload;
             WriteDataChannelOpenAckMessage(&payload);
             SendControlMessage(payload);
           }
@@ -595,11 +595,11 @@
   }
 }
 
-void DataChannel::QueueControlMessage(const rtc::Buffer& buffer) {
+void DataChannel::QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer) {
   queued_control_data_.Push(new DataBuffer(buffer, true));
 }
 
-bool DataChannel::SendControlMessage(const rtc::Buffer& buffer) {
+bool DataChannel::SendControlMessage(const rtc::CopyOnWriteBuffer& buffer) {
   bool is_open_message = handshake_state_ == kHandshakeShouldSendOpen;
 
   ASSERT(data_channel_type_ == cricket::DCT_SCTP &&
diff --git a/webrtc/api/datachannel.h b/webrtc/api/datachannel.h
index 62e3eaf..b8830be 100644
--- a/webrtc/api/datachannel.h
+++ b/webrtc/api/datachannel.h
@@ -31,7 +31,7 @@
  public:
   // Sends the data to the transport.
   virtual bool SendData(const cricket::SendDataParams& params,
-                        const rtc::Buffer& payload,
+                        const rtc::CopyOnWriteBuffer& payload,
                         cricket::SendDataResult* result) = 0;
   // Connects to the transport signals.
   virtual bool ConnectDataChannel(DataChannel* data_channel) = 0;
@@ -143,7 +143,7 @@
   // Sigslots from cricket::DataChannel
   void OnDataReceived(cricket::DataChannel* channel,
                       const cricket::ReceiveDataParams& params,
-                      const rtc::Buffer& payload);
+                      const rtc::CopyOnWriteBuffer& payload);
   void OnStreamClosedRemotely(uint32_t sid);
 
   // The remote peer request that this channel should be closed.
@@ -236,8 +236,8 @@
   bool QueueSendDataMessage(const DataBuffer& buffer);
 
   void SendQueuedControlMessages();
-  void QueueControlMessage(const rtc::Buffer& buffer);
-  bool SendControlMessage(const rtc::Buffer& buffer);
+  void QueueControlMessage(const rtc::CopyOnWriteBuffer& buffer);
+  bool SendControlMessage(const rtc::CopyOnWriteBuffer& buffer);
 
   std::string label_;
   InternalDataChannelInit config_;
diff --git a/webrtc/api/datachannel_unittest.cc b/webrtc/api/datachannel_unittest.cc
index 880c2aa..5958ec0 100644
--- a/webrtc/api/datachannel_unittest.cc
+++ b/webrtc/api/datachannel_unittest.cc
@@ -246,7 +246,7 @@
   cricket::ReceiveDataParams params;
   params.ssrc = init.id;
   params.type = cricket::DMT_CONTROL;
-  rtc::Buffer payload;
+  rtc::CopyOnWriteBuffer payload;
   webrtc::WriteDataChannelOpenAckMessage(&payload);
   dc->OnDataReceived(NULL, params, payload);
 
@@ -404,7 +404,7 @@
 TEST_F(SctpDataChannelTest, ClosedWhenSendBufferFull) {
   SetChannelReady();
 
-  rtc::Buffer buffer(1024);
+  rtc::CopyOnWriteBuffer buffer(1024);
   memset(buffer.data(), 0, buffer.size());
 
   webrtc::DataBuffer packet(buffer, true);
@@ -457,7 +457,7 @@
 // Tests that the DataChannel is closed if the received buffer is full.
 TEST_F(SctpDataChannelTest, ClosedWhenReceivedBufferFull) {
   SetChannelReady();
-  rtc::Buffer buffer(1024);
+  rtc::CopyOnWriteBuffer buffer(1024);
   memset(buffer.data(), 0, buffer.size());
 
   cricket::ReceiveDataParams params;
diff --git a/webrtc/api/datachannelinterface.h b/webrtc/api/datachannelinterface.h
index 3d6f711..53c11d4 100644
--- a/webrtc/api/datachannelinterface.h
+++ b/webrtc/api/datachannelinterface.h
@@ -17,8 +17,8 @@
 #include <string>
 
 #include "webrtc/base/basictypes.h"
-#include "webrtc/base/buffer.h"
 #include "webrtc/base/checks.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/refcount.h"
 
 
@@ -50,7 +50,7 @@
 };
 
 struct DataBuffer {
-  DataBuffer(const rtc::Buffer& data, bool binary)
+  DataBuffer(const rtc::CopyOnWriteBuffer& data, bool binary)
       : data(data),
         binary(binary) {
   }
@@ -61,7 +61,7 @@
   }
   size_t size() const { return data.size(); }
 
-  rtc::Buffer data;
+  rtc::CopyOnWriteBuffer data;
   // Indicates if the received data contains UTF-8 or binary data.
   // Note that the upper layers are left to verify the UTF-8 encoding.
   // TODO(jiayl): prefer to use an enum instead of a bool.
diff --git a/webrtc/api/java/jni/peerconnection_jni.cc b/webrtc/api/java/jni/peerconnection_jni.cc
index d614ed6..6c8192d 100644
--- a/webrtc/api/java/jni/peerconnection_jni.cc
+++ b/webrtc/api/java/jni/peerconnection_jni.cc
@@ -893,7 +893,7 @@
                                       jbyteArray data, jboolean binary) {
   jbyte* bytes = jni->GetByteArrayElements(data, NULL);
   bool ret = ExtractNativeDC(jni, j_dc)->Send(DataBuffer(
-      rtc::Buffer(bytes, jni->GetArrayLength(data)),
+      rtc::CopyOnWriteBuffer(bytes, jni->GetArrayLength(data)),
       binary));
   jni->ReleaseByteArrayElements(data, bytes, JNI_ABORT);
   return ret;
diff --git a/webrtc/api/objc/RTCDataChannel.mm b/webrtc/api/objc/RTCDataChannel.mm
index 5778cb5..9859905 100644
--- a/webrtc/api/objc/RTCDataChannel.mm
+++ b/webrtc/api/objc/RTCDataChannel.mm
@@ -53,8 +53,8 @@
 - (instancetype)initWithData:(NSData *)data isBinary:(BOOL)isBinary {
   NSParameterAssert(data);
   if (self = [super init]) {
-    rtc::Buffer buffer(reinterpret_cast<const uint8_t*>(data.bytes),
-                       data.length);
+    rtc::CopyOnWriteBuffer buffer(
+        reinterpret_cast<const uint8_t*>(data.bytes), data.length);
     _dataBuffer.reset(new webrtc::DataBuffer(buffer, isBinary));
   }
   return self;
diff --git a/webrtc/api/peerconnectioninterface_unittest.cc b/webrtc/api/peerconnectioninterface_unittest.cc
index 6bff11a..d4678ba 100644
--- a/webrtc/api/peerconnectioninterface_unittest.cc
+++ b/webrtc/api/peerconnectioninterface_unittest.cc
@@ -1400,7 +1400,7 @@
   EXPECT_EQ(DataChannelInterface::kOpen, data1->state());
   EXPECT_EQ(DataChannelInterface::kOpen, data2->state());
 
-  rtc::Buffer buffer("test", 4);
+  rtc::CopyOnWriteBuffer buffer("test", 4);
   EXPECT_FALSE(data1->Send(DataBuffer(buffer, true)));
 }
 
diff --git a/webrtc/api/sctputils.cc b/webrtc/api/sctputils.cc
index 1a2c282..f2d1b0f 100644
--- a/webrtc/api/sctputils.cc
+++ b/webrtc/api/sctputils.cc
@@ -10,8 +10,8 @@
 
 #include "webrtc/api/sctputils.h"
 
-#include "webrtc/base/buffer.h"
 #include "webrtc/base/bytebuffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/logging.h"
 
 namespace webrtc {
@@ -31,26 +31,27 @@
   DCOMCT_UNORDERED_PARTIAL_TIME = 0x82,
 };
 
-bool IsOpenMessage(const rtc::Buffer& payload) {
+bool IsOpenMessage(const rtc::CopyOnWriteBuffer& payload) {
   // Format defined at
   // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
-
-  rtc::ByteBuffer buffer(payload);
-  uint8_t message_type;
-  if (!buffer.ReadUInt8(&message_type)) {
+  if (payload.size() < 1) {
     LOG(LS_WARNING) << "Could not read OPEN message type.";
     return false;
   }
+
+  uint8_t message_type = payload[0];
   return message_type == DATA_CHANNEL_OPEN_MESSAGE_TYPE;
 }
 
-bool ParseDataChannelOpenMessage(const rtc::Buffer& payload,
+bool ParseDataChannelOpenMessage(const rtc::CopyOnWriteBuffer& payload,
                                  std::string* label,
                                  DataChannelInit* config) {
   // Format defined at
   // http://tools.ietf.org/html/draft-jesup-rtcweb-data-protocol-04
 
-  rtc::ByteBuffer buffer(payload);
+  // TODO(jbauch): avoid copying the payload data into the ByteBuffer, see
+  // https://bugs.chromium.org/p/webrtc/issues/detail?id=5670
+  rtc::ByteBuffer buffer(payload.data<char>(), payload.size());
   uint8_t message_type;
   if (!buffer.ReadUInt8(&message_type)) {
     LOG(LS_WARNING) << "Could not read OPEN message type.";
@@ -120,13 +121,13 @@
   return true;
 }
 
-bool ParseDataChannelOpenAckMessage(const rtc::Buffer& payload) {
-  rtc::ByteBuffer buffer(payload);
-  uint8_t message_type;
-  if (!buffer.ReadUInt8(&message_type)) {
+bool ParseDataChannelOpenAckMessage(const rtc::CopyOnWriteBuffer& payload) {
+  if (payload.size() < 1) {
     LOG(LS_WARNING) << "Could not read OPEN_ACK message type.";
     return false;
   }
+
+  uint8_t message_type = payload[0];
   if (message_type != DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE) {
     LOG(LS_WARNING) << "Data Channel OPEN_ACK message of unexpected type: "
                     << message_type;
@@ -137,7 +138,7 @@
 
 bool WriteDataChannelOpenMessage(const std::string& label,
                                  const DataChannelInit& config,
-                                 rtc::Buffer* payload) {
+                                 rtc::CopyOnWriteBuffer* payload) {
   // Format defined at
   // http://tools.ietf.org/html/draft-ietf-rtcweb-data-protocol-00#section-6.1
   uint8_t channel_type = 0;
@@ -168,6 +169,7 @@
   rtc::ByteBuffer buffer(
       NULL, 20 + label.length() + config.protocol.length(),
       rtc::ByteBuffer::ORDER_NETWORK);
+  // TODO(tommi): Add error handling and check resulting length.
   buffer.WriteUInt8(DATA_CHANNEL_OPEN_MESSAGE_TYPE);
   buffer.WriteUInt8(channel_type);
   buffer.WriteUInt16(priority);
@@ -180,9 +182,9 @@
   return true;
 }
 
-void WriteDataChannelOpenAckMessage(rtc::Buffer* payload) {
-  rtc::ByteBuffer buffer(rtc::ByteBuffer::ORDER_NETWORK);
-  buffer.WriteUInt8(DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE);
-  payload->SetData(buffer.Data(), buffer.Length());
+void WriteDataChannelOpenAckMessage(rtc::CopyOnWriteBuffer* payload) {
+  uint8_t data = DATA_CHANNEL_OPEN_ACK_MESSAGE_TYPE;
+  payload->SetData(&data, sizeof(data));
 }
+
 }  // namespace webrtc
diff --git a/webrtc/api/sctputils.h b/webrtc/api/sctputils.h
index ffbade2..2fb1943 100644
--- a/webrtc/api/sctputils.h
+++ b/webrtc/api/sctputils.h
@@ -16,26 +16,26 @@
 #include "webrtc/api/datachannelinterface.h"
 
 namespace rtc {
-class Buffer;
+class CopyOnWriteBuffer;
 }  // namespace rtc
 
 namespace webrtc {
 struct DataChannelInit;
 
 // Read the message type and return true if it's an OPEN message.
-bool IsOpenMessage(const rtc::Buffer& payload);
+bool IsOpenMessage(const rtc::CopyOnWriteBuffer& payload);
 
-bool ParseDataChannelOpenMessage(const rtc::Buffer& payload,
+bool ParseDataChannelOpenMessage(const rtc::CopyOnWriteBuffer& payload,
                                  std::string* label,
                                  DataChannelInit* config);
 
-bool ParseDataChannelOpenAckMessage(const rtc::Buffer& payload);
+bool ParseDataChannelOpenAckMessage(const rtc::CopyOnWriteBuffer& payload);
 
 bool WriteDataChannelOpenMessage(const std::string& label,
                                  const DataChannelInit& config,
-                                 rtc::Buffer* payload);
+                                 rtc::CopyOnWriteBuffer* payload);
 
-void WriteDataChannelOpenAckMessage(rtc::Buffer* payload);
+void WriteDataChannelOpenAckMessage(rtc::CopyOnWriteBuffer* payload);
 }  // namespace webrtc
 
 #endif  // WEBRTC_API_SCTPUTILS_H_
diff --git a/webrtc/api/test/fakedatachannelprovider.h b/webrtc/api/test/fakedatachannelprovider.h
index 7899c31..3404ac1 100644
--- a/webrtc/api/test/fakedatachannelprovider.h
+++ b/webrtc/api/test/fakedatachannelprovider.h
@@ -23,7 +23,7 @@
   virtual ~FakeDataChannelProvider() {}
 
   bool SendData(const cricket::SendDataParams& params,
-                const rtc::Buffer& payload,
+                const rtc::CopyOnWriteBuffer& payload,
                 cricket::SendDataResult* result) override {
     ASSERT(ready_to_send_ && transport_available_);
     if (send_blocked_) {
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index 593d429..19f5aa4 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -1374,7 +1374,7 @@
 }
 
 bool WebRtcSession::SendData(const cricket::SendDataParams& params,
-                             const rtc::Buffer& payload,
+                             const rtc::CopyOnWriteBuffer& payload,
                              cricket::SendDataResult* result) {
   if (!data_channel_) {
     LOG(LS_ERROR) << "SendData called when data_channel_ is NULL.";
@@ -1854,7 +1854,7 @@
 void WebRtcSession::OnDataChannelMessageReceived(
     cricket::DataChannel* channel,
     const cricket::ReceiveDataParams& params,
-    const rtc::Buffer& payload) {
+    const rtc::CopyOnWriteBuffer& payload) {
   RTC_DCHECK(data_channel_type_ == cricket::DCT_SCTP);
   if (params.type == cricket::DMT_CONTROL && IsOpenMessage(payload)) {
     // Received OPEN message; parse and signal that a new data channel should
diff --git a/webrtc/api/webrtcsession.h b/webrtc/api/webrtcsession.h
index e884678..6164731 100644
--- a/webrtc/api/webrtcsession.h
+++ b/webrtc/api/webrtcsession.h
@@ -271,7 +271,7 @@
 
   // Implements DataChannelProviderInterface.
   bool SendData(const cricket::SendDataParams& params,
-                const rtc::Buffer& payload,
+                const rtc::CopyOnWriteBuffer& payload,
                 cricket::SendDataResult* result) override;
   bool ConnectDataChannel(DataChannel* webrtc_data_channel) override;
   void DisconnectDataChannel(DataChannel* webrtc_data_channel) override;
@@ -413,7 +413,7 @@
   // messages.
   void OnDataChannelMessageReceived(cricket::DataChannel* channel,
                                     const cricket::ReceiveDataParams& params,
-                                    const rtc::Buffer& payload);
+                                    const rtc::CopyOnWriteBuffer& payload);
 
   std::string BadStateErrMsg(State state);
   void SetIceConnectionState(PeerConnectionInterface::IceConnectionState state);
diff --git a/webrtc/api/webrtcsession_unittest.cc b/webrtc/api/webrtcsession_unittest.cc
index 77c4854..18c1a95 100644
--- a/webrtc/api/webrtcsession_unittest.cc
+++ b/webrtc/api/webrtcsession_unittest.cc
@@ -4054,7 +4054,7 @@
 
   webrtc::DataChannelInit config;
   config.id = 1;
-  rtc::Buffer payload;
+  rtc::CopyOnWriteBuffer payload;
   webrtc::WriteDataChannelOpenMessage("a", config, &payload);
   cricket::ReceiveDataParams params;
   params.ssrc = config.id;
diff --git a/webrtc/base/buffer.cc b/webrtc/base/buffer.cc
index 3096cc9..6051e6d 100644
--- a/webrtc/base/buffer.cc
+++ b/webrtc/base/buffer.cc
@@ -19,9 +19,6 @@
   RTC_DCHECK(IsConsistent());
 }
 
-Buffer::Buffer(const Buffer& buf) : Buffer(buf.data(), buf.size()) {
-}
-
 Buffer::Buffer(Buffer&& buf)
     : size_(buf.size()),
       capacity_(buf.capacity()),
diff --git a/webrtc/base/buffer.h b/webrtc/base/buffer.h
index 681348d..f007929 100644
--- a/webrtc/base/buffer.h
+++ b/webrtc/base/buffer.h
@@ -49,7 +49,6 @@
 class Buffer {
  public:
   Buffer();                   // An empty buffer.
-  Buffer(const Buffer& buf);  // Copy size and contents of an existing buffer.
   Buffer(Buffer&& buf);       // Move contents from an existing buffer.
 
   // Construct a buffer with the specified number of uninitialized bytes.
@@ -99,12 +98,6 @@
     return capacity_;
   }
 
-  Buffer& operator=(const Buffer& buf) {
-    if (&buf != this)
-      SetData(buf.data(), buf.size());
-    return *this;
-  }
-
   Buffer& operator=(Buffer&& buf) {
     RTC_DCHECK(IsConsistent());
     RTC_DCHECK(buf.IsConsistent());
@@ -270,6 +263,8 @@
   size_t size_;
   size_t capacity_;
   std::unique_ptr<uint8_t[]> data_;
+
+  RTC_DISALLOW_COPY_AND_ASSIGN(Buffer);
 };
 
 }  // namespace rtc
diff --git a/webrtc/base/buffer_unittest.cc b/webrtc/base/buffer_unittest.cc
index 7c65447..2f3bcfd 100644
--- a/webrtc/base/buffer_unittest.cc
+++ b/webrtc/base/buffer_unittest.cc
@@ -64,23 +64,6 @@
   EXPECT_EQ(0, memcmp(buf.data(), kTestData, 16));
 }
 
-TEST(BufferTest, TestConstructCopy) {
-  Buffer buf1(kTestData), buf2(buf1);
-  EXPECT_EQ(buf2.size(), 16u);
-  EXPECT_EQ(buf2.capacity(), 16u);
-  EXPECT_EQ(0, memcmp(buf2.data(), kTestData, 16));
-  EXPECT_NE(buf1.data(), buf2.data());
-  EXPECT_EQ(buf1, buf2);
-}
-
-TEST(BufferTest, TestAssign) {
-  Buffer buf1, buf2(kTestData, sizeof(kTestData), 256);
-  EXPECT_NE(buf1, buf2);
-  buf1 = buf2;
-  EXPECT_EQ(buf1, buf2);
-  EXPECT_NE(buf1.data(), buf2.data());
-}
-
 TEST(BufferTest, TestSetData) {
   Buffer buf(kTestData + 4, 7);
   buf.SetData(kTestData, 9);
diff --git a/webrtc/base/copyonwritebuffer.h b/webrtc/base/copyonwritebuffer.h
index 17f2710..87f24bf 100644
--- a/webrtc/base/copyonwritebuffer.h
+++ b/webrtc/base/copyonwritebuffer.h
@@ -42,7 +42,9 @@
   template <typename T, typename internal::ByteType<T>::t = 0>
   CopyOnWriteBuffer(const T* data, size_t size, size_t capacity)
       : CopyOnWriteBuffer(size, capacity) {
-    std::memcpy(buffer_->data(), data, size);
+    if (buffer_) {
+      std::memcpy(buffer_->data(), data, size);
+    }
   }
 
   // Construct a buffer from the contents of an array.
@@ -123,13 +125,24 @@
     return !(*this == buf);
   }
 
+  uint8_t& operator[](size_t index) {
+    RTC_DCHECK_LT(index, size());
+    return data()[index];
+  }
+
+  uint8_t operator[](size_t index) const {
+    RTC_DCHECK_LT(index, size());
+    return cdata()[index];
+  }
+
   // Replace the contents of the buffer. Accepts the same types as the
   // constructors.
   template <typename T, typename internal::ByteType<T>::t = 0>
   void SetData(const T* data, size_t size) {
     RTC_DCHECK(IsConsistent());
     if (!buffer_ || !buffer_->HasOneRef()) {
-      buffer_ = new RefCountedObject<Buffer>(data, size, size);
+      buffer_ = size > 0 ? new RefCountedObject<Buffer>(data, size)
+                         : nullptr;
     } else {
       buffer_->SetData(data, size);
     }
diff --git a/webrtc/base/copyonwritebuffer_unittest.cc b/webrtc/base/copyonwritebuffer_unittest.cc
index a95ad67..dbf59f7 100644
--- a/webrtc/base/copyonwritebuffer_unittest.cc
+++ b/webrtc/base/copyonwritebuffer_unittest.cc
@@ -41,6 +41,13 @@
   EXPECT_NE(data1, data2);
 }
 
+TEST(CopyOnWriteBufferTest, TestCreateEmptyData) {
+  CopyOnWriteBuffer buf(static_cast<const uint8_t*>(nullptr), 0);
+  EXPECT_EQ(buf.size(), 0u);
+  EXPECT_EQ(buf.capacity(), 0u);
+  EXPECT_EQ(buf.data(), nullptr);
+}
+
 TEST(CopyOnWriteBufferTest, TestMoveConstruct) {
   CopyOnWriteBuffer buf1(kTestData, 3, 10);
   size_t buf1_size = buf1.size();
@@ -125,6 +132,21 @@
   EnsureBuffersDontShareData(buf1, buf3);
   const int8_t exp[] = {'f', 'o', 'o', 0x0};
   EXPECT_EQ(buf3, CopyOnWriteBuffer(exp));
+
+  buf2.SetData(static_cast<const uint8_t*>(nullptr), 0u);
+  EnsureBuffersDontShareData(buf1, buf2);
+  EXPECT_EQ(buf1.size(), 3u);
+  EXPECT_EQ(buf1.capacity(), 10u);
+  EXPECT_EQ(buf2.size(), 0u);
+  EXPECT_EQ(buf2.capacity(), 0u);
+}
+
+TEST(CopyOnWriteBufferTest, TestSetDataEmpty) {
+  CopyOnWriteBuffer buf;
+  buf.SetData(static_cast<const uint8_t*>(nullptr), 0u);
+  EXPECT_EQ(buf.size(), 0u);
+  EXPECT_EQ(buf.capacity(), 0u);
+  EXPECT_EQ(buf.data(), nullptr);
 }
 
 TEST(CopyOnWriteBufferTest, TestEnsureCapacity) {
@@ -196,4 +218,43 @@
   EXPECT_EQ(data2, cdata1);
 }
 
+TEST(CopyOnWriteBufferTest, TestBacketRead) {
+  CopyOnWriteBuffer buf1(kTestData, 3, 10);
+  CopyOnWriteBuffer buf2(buf1);
+
+  EnsureBuffersShareData(buf1, buf2);
+  // Non-const reads clone the data if shared.
+  for (size_t i = 0; i != 3u; ++i) {
+    EXPECT_EQ(buf1[i], kTestData[i]);
+  }
+  EnsureBuffersDontShareData(buf1, buf2);
+}
+
+TEST(CopyOnWriteBufferTest, TestBacketReadConst) {
+  CopyOnWriteBuffer buf1(kTestData, 3, 10);
+  CopyOnWriteBuffer buf2(buf1);
+
+  EnsureBuffersShareData(buf1, buf2);
+  const CopyOnWriteBuffer& cbuf1 = buf1;
+  for (size_t i = 0; i != 3u; ++i) {
+    EXPECT_EQ(cbuf1[i], kTestData[i]);
+  }
+  EnsureBuffersShareData(buf1, buf2);
+}
+
+TEST(CopyOnWriteBufferTest, TestBacketWrite) {
+  CopyOnWriteBuffer buf1(kTestData, 3, 10);
+  CopyOnWriteBuffer buf2(buf1);
+
+  EnsureBuffersShareData(buf1, buf2);
+  for (size_t i = 0; i != 3u; ++i) {
+    buf1[i] = kTestData[i] + 1;
+  }
+  EXPECT_EQ(buf1.size(), 3u);
+  EXPECT_EQ(buf1.capacity(), 10u);
+  EXPECT_EQ(buf2.size(), 3u);
+  EXPECT_EQ(buf2.capacity(), 10u);
+  EXPECT_EQ(0, memcmp(buf2.cdata(), kTestData, 3));
+}
+
 }  // namespace rtc
diff --git a/webrtc/base/sslfingerprint.h b/webrtc/base/sslfingerprint.h
index 735238d..1413a4c 100644
--- a/webrtc/base/sslfingerprint.h
+++ b/webrtc/base/sslfingerprint.h
@@ -14,7 +14,7 @@
 #include <string>
 
 #include "webrtc/base/basictypes.h"
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/sslidentity.h"
 
 namespace rtc {
@@ -44,7 +44,7 @@
   std::string ToString();
 
   std::string algorithm;
-  rtc::Buffer digest;
+  rtc::CopyOnWriteBuffer digest;
 };
 
 }  // namespace rtc
diff --git a/webrtc/media/base/fakemediaengine.h b/webrtc/media/base/fakemediaengine.h
index 7f9561d..af05144 100644
--- a/webrtc/media/base/fakemediaengine.h
+++ b/webrtc/media/base/fakemediaengine.h
@@ -19,7 +19,7 @@
 #include <vector>
 
 #include "webrtc/audio_sink.h"
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/stringutils.h"
 #include "webrtc/media/base/audiosource.h"
 #include "webrtc/media/base/mediaengine.h"
@@ -58,13 +58,13 @@
     if (!sending_) {
       return false;
     }
-    rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len,
-                       kMaxRtpPacketLen);
+    rtc::CopyOnWriteBuffer packet(reinterpret_cast<const uint8_t*>(data), len,
+                                  kMaxRtpPacketLen);
     return Base::SendPacket(&packet, options);
   }
   bool SendRtcp(const void* data, int len) {
-    rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len,
-                       kMaxRtpPacketLen);
+    rtc::CopyOnWriteBuffer packet(reinterpret_cast<const uint8_t*>(data), len,
+                                  kMaxRtpPacketLen);
     return Base::SendRtcp(&packet, rtc::PacketOptions());
   }
 
@@ -205,11 +205,11 @@
     send_extensions_ = extensions;
     return true;
   }
-  virtual void OnPacketReceived(rtc::Buffer* packet,
+  virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                                 const rtc::PacketTime& packet_time) {
     rtp_packets_.push_back(std::string(packet->data<char>(), packet->size()));
   }
-  virtual void OnRtcpReceived(rtc::Buffer* packet,
+  virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) {
     rtcp_packets_.push_back(std::string(packet->data<char>(), packet->size()));
   }
@@ -609,7 +609,7 @@
   }
 
   virtual bool SendData(const SendDataParams& params,
-                        const rtc::Buffer& payload,
+                        const rtc::CopyOnWriteBuffer& payload,
                         SendDataResult* result) {
     if (send_blocked_) {
       *result = SDR_BLOCK;
diff --git a/webrtc/media/base/fakenetworkinterface.h b/webrtc/media/base/fakenetworkinterface.h
index d9caac0..65dac25 100644
--- a/webrtc/media/base/fakenetworkinterface.h
+++ b/webrtc/media/base/fakenetworkinterface.h
@@ -14,8 +14,8 @@
 #include <map>
 #include <vector>
 
-#include "webrtc/base/buffer.h"
 #include "webrtc/base/byteorder.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/dscp.h"
 #include "webrtc/base/messagehandler.h"
@@ -84,12 +84,12 @@
   }
 
   // Note: callers are responsible for deleting the returned buffer.
-  const rtc::Buffer* GetRtpPacket(int index) {
+  const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) {
     rtc::CritScope cs(&crit_);
     if (index >= NumRtpPackets()) {
       return NULL;
     }
-    return new rtc::Buffer(rtp_packets_[index]);
+    return new rtc::CopyOnWriteBuffer(rtp_packets_[index]);
   }
 
   int NumRtcpPackets() {
@@ -98,12 +98,12 @@
   }
 
   // Note: callers are responsible for deleting the returned buffer.
-  const rtc::Buffer* GetRtcpPacket(int index) {
+  const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) {
     rtc::CritScope cs(&crit_);
     if (index >= NumRtcpPackets()) {
       return NULL;
     }
-    return new rtc::Buffer(rtcp_packets_[index]);
+    return new rtc::CopyOnWriteBuffer(rtcp_packets_[index]);
   }
 
   int sendbuf_size() const { return sendbuf_size_; }
@@ -111,7 +111,7 @@
   rtc::DiffServCodePoint dscp() const { return dscp_; }
 
  protected:
-  virtual bool SendPacket(rtc::Buffer* packet,
+  virtual bool SendPacket(rtc::CopyOnWriteBuffer* packet,
                           const rtc::PacketOptions& options) {
     rtc::CritScope cs(&crit_);
 
@@ -123,13 +123,12 @@
 
     rtp_packets_.push_back(*packet);
     if (conf_) {
-      rtc::Buffer buffer_copy(*packet);
       for (size_t i = 0; i < conf_sent_ssrcs_.size(); ++i) {
-        if (!SetRtpSsrc(buffer_copy.data(), buffer_copy.size(),
+        if (!SetRtpSsrc(packet->data(), packet->size(),
                         conf_sent_ssrcs_[i])) {
           return false;
         }
-        PostMessage(ST_RTP, buffer_copy);
+        PostMessage(ST_RTP, *packet);
       }
     } else {
       PostMessage(ST_RTP, *packet);
@@ -137,7 +136,7 @@
     return true;
   }
 
-  virtual bool SendRtcp(rtc::Buffer* packet,
+  virtual bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
                         const rtc::PacketOptions& options) {
     rtc::CritScope cs(&crit_);
     rtcp_packets_.push_back(*packet);
@@ -160,13 +159,13 @@
     return 0;
   }
 
-  void PostMessage(int id, const rtc::Buffer& packet) {
+  void PostMessage(int id, const rtc::CopyOnWriteBuffer& packet) {
     thread_->Post(this, id, rtc::WrapMessageData(packet));
   }
 
   virtual void OnMessage(rtc::Message* msg) {
-    rtc::TypedMessageData<rtc::Buffer>* msg_data =
-        static_cast<rtc::TypedMessageData<rtc::Buffer>*>(
+    rtc::TypedMessageData<rtc::CopyOnWriteBuffer>* msg_data =
+        static_cast<rtc::TypedMessageData<rtc::CopyOnWriteBuffer>*>(
             msg->pdata);
     if (dest_) {
       if (msg->message_id == ST_RTP) {
@@ -216,8 +215,8 @@
   // Map to track packet-number that needs to be dropped per ssrc.
   std::map<uint32_t, std::set<uint32_t> > drop_map_;
   rtc::CriticalSection crit_;
-  std::vector<rtc::Buffer> rtp_packets_;
-  std::vector<rtc::Buffer> rtcp_packets_;
+  std::vector<rtc::CopyOnWriteBuffer> rtp_packets_;
+  std::vector<rtc::CopyOnWriteBuffer> rtcp_packets_;
   int sendbuf_size_;
   int recvbuf_size_;
   rtc::DiffServCodePoint dscp_;
diff --git a/webrtc/media/base/mediachannel.h b/webrtc/media/base/mediachannel.h
index ed565ee..95355c9 100644
--- a/webrtc/media/base/mediachannel.h
+++ b/webrtc/media/base/mediachannel.h
@@ -17,7 +17,7 @@
 
 #include "webrtc/api/rtpparameters.h"
 #include "webrtc/base/basictypes.h"
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/dscp.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/optional.h"
@@ -356,9 +356,9 @@
   class NetworkInterface {
    public:
     enum SocketType { ST_RTP, ST_RTCP };
-    virtual bool SendPacket(rtc::Buffer* packet,
+    virtual bool SendPacket(rtc::CopyOnWriteBuffer* packet,
                             const rtc::PacketOptions& options) = 0;
-    virtual bool SendRtcp(rtc::Buffer* packet,
+    virtual bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
                           const rtc::PacketOptions& options) = 0;
     virtual int SetOption(SocketType type, rtc::Socket::Option opt,
                           int option) = 0;
@@ -380,10 +380,10 @@
     return rtc::DSCP_DEFAULT;
   }
   // Called when a RTP packet is received.
-  virtual void OnPacketReceived(rtc::Buffer* packet,
+  virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                                 const rtc::PacketTime& packet_time) = 0;
   // Called when a RTCP packet is received.
-  virtual void OnRtcpReceived(rtc::Buffer* packet,
+  virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) = 0;
   // Called when the socket's ability to send has changed.
   virtual void OnReadyToSend(bool ready) = 0;
@@ -408,11 +408,13 @@
   }
 
   // Base method to send packet using NetworkInterface.
-  bool SendPacket(rtc::Buffer* packet, const rtc::PacketOptions& options) {
+  bool SendPacket(rtc::CopyOnWriteBuffer* packet,
+                  const rtc::PacketOptions& options) {
     return DoSendPacket(packet, false, options);
   }
 
-  bool SendRtcp(rtc::Buffer* packet, const rtc::PacketOptions& options) {
+  bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
+                const rtc::PacketOptions& options) {
     return DoSendPacket(packet, true, options);
   }
 
@@ -441,7 +443,7 @@
     return ret;
   }
 
-  bool DoSendPacket(rtc::Buffer* packet,
+  bool DoSendPacket(rtc::CopyOnWriteBuffer* packet,
                     bool rtcp,
                     const rtc::PacketOptions& options) {
     rtc::CritScope cs(&network_interface_crit_);
@@ -1104,7 +1106,7 @@
 
   virtual bool SendData(
       const SendDataParams& params,
-      const rtc::Buffer& payload,
+      const rtc::CopyOnWriteBuffer& payload,
       SendDataResult* result = NULL) = 0;
   // Signals when data is received (params, data, len)
   sigslot::signal3<const ReceiveDataParams&,
diff --git a/webrtc/media/base/rtpdataengine.cc b/webrtc/media/base/rtpdataengine.cc
index 705ccbd..ae36174 100644
--- a/webrtc/media/base/rtpdataengine.cc
+++ b/webrtc/media/base/rtpdataengine.cc
@@ -10,7 +10,7 @@
 
 #include "webrtc/media/base/rtpdataengine.h"
 
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/ratelimiter.h"
@@ -205,9 +205,9 @@
 }
 
 void RtpDataMediaChannel::OnPacketReceived(
-    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
+    rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
   RtpHeader header;
-  if (!GetRtpHeader(packet->data(), packet->size(), &header)) {
+  if (!GetRtpHeader(packet->cdata(), packet->size(), &header)) {
     // Don't want to log for every corrupt packet.
     // LOG(LS_WARNING) << "Could not read rtp header from packet of length "
     //                 << packet->length() << ".";
@@ -215,7 +215,7 @@
   }
 
   size_t header_length;
-  if (!GetRtpHeaderLen(packet->data(), packet->size(), &header_length)) {
+  if (!GetRtpHeaderLen(packet->cdata(), packet->size(), &header_length)) {
     // Don't want to log for every corrupt packet.
     // LOG(LS_WARNING) << "Could not read rtp header"
     //                 << length from packet of length "
@@ -223,7 +223,7 @@
     return;
   }
   const char* data =
-      packet->data<char>() + header_length + sizeof(kReservedSpace);
+      packet->cdata<char>() + header_length + sizeof(kReservedSpace);
   size_t data_len = packet->size() - header_length - sizeof(kReservedSpace);
 
   if (!receiving_) {
@@ -276,7 +276,7 @@
 
 bool RtpDataMediaChannel::SendData(
     const SendDataParams& params,
-    const rtc::Buffer& payload,
+    const rtc::CopyOnWriteBuffer& payload,
     SendDataResult* result) {
   if (result) {
     // If we return true, we'll set this to SDR_SUCCESS.
@@ -329,7 +329,7 @@
   rtp_clock_by_send_ssrc_[header.ssrc]->Tick(
       now, &header.seq_num, &header.timestamp);
 
-  rtc::Buffer packet(kMinRtpPacketLen, packet_len);
+  rtc::CopyOnWriteBuffer packet(kMinRtpPacketLen, packet_len);
   if (!SetRtpHeader(packet.data(), packet.size(), header)) {
     return false;
   }
diff --git a/webrtc/media/base/rtpdataengine.h b/webrtc/media/base/rtpdataengine.h
index 62eebf6..0181e65 100644
--- a/webrtc/media/base/rtpdataengine.h
+++ b/webrtc/media/base/rtpdataengine.h
@@ -93,14 +93,14 @@
     receiving_ = receive;
     return true;
   }
-  virtual void OnPacketReceived(rtc::Buffer* packet,
+  virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                                 const rtc::PacketTime& packet_time);
-  virtual void OnRtcpReceived(rtc::Buffer* packet,
+  virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) {}
   virtual void OnReadyToSend(bool ready) {}
   virtual bool SendData(
     const SendDataParams& params,
-    const rtc::Buffer& payload,
+    const rtc::CopyOnWriteBuffer& payload,
     SendDataResult* result);
 
  private:
diff --git a/webrtc/media/base/rtpdataengine_unittest.cc b/webrtc/media/base/rtpdataengine_unittest.cc
index 2a9b25e..b5cfd32 100644
--- a/webrtc/media/base/rtpdataengine_unittest.cc
+++ b/webrtc/media/base/rtpdataengine_unittest.cc
@@ -11,7 +11,7 @@
 #include <memory>
 #include <string>
 
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/ssladapter.h"
@@ -124,7 +124,7 @@
 
   std::string GetSentData(int index) {
     // Assume RTP header of length 12
-    std::unique_ptr<const rtc::Buffer> packet(
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
         iface_->GetRtpPacket(index));
     if (packet->size() > 12) {
       return std::string(packet->data<char>() + 12, packet->size() - 12);
@@ -134,7 +134,7 @@
   }
 
   cricket::RtpHeader GetSentDataHeader(int index) {
-    std::unique_ptr<const rtc::Buffer> packet(
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
         iface_->GetRtpPacket(index));
     cricket::RtpHeader header;
     GetRtpHeader(packet->data(), packet->size(), &header);
@@ -220,7 +220,7 @@
   cricket::SendDataParams params;
   params.ssrc = 42;
   unsigned char data[] = "food";
-  rtc::Buffer payload(data, 4);
+  rtc::CopyOnWriteBuffer payload(data, 4);
   unsigned char padded_data[] = {
     0x00, 0x00, 0x00, 0x00,
     'f', 'o', 'o', 'd',
@@ -257,7 +257,7 @@
   // Length too large;
   std::string x10000(10000, 'x');
   EXPECT_FALSE(dmc->SendData(
-      params, rtc::Buffer(x10000.data(), x10000.length()), &result));
+      params, rtc::CopyOnWriteBuffer(x10000.data(), x10000.length()), &result));
   EXPECT_EQ(cricket::SDR_ERROR, result);
   EXPECT_FALSE(HasSentData(0));
 
@@ -325,7 +325,7 @@
   params2.ssrc = 42;
 
   unsigned char data[] = "foo";
-  rtc::Buffer payload(data, 3);
+  rtc::CopyOnWriteBuffer payload(data, 3);
   cricket::SendDataResult result;
 
   EXPECT_TRUE(dmc1->SendData(params1, payload, &result));
@@ -372,7 +372,7 @@
   cricket::SendDataParams params;
   params.ssrc = 42;
   unsigned char data[] = "food";
-  rtc::Buffer payload(data, 4);
+  rtc::CopyOnWriteBuffer payload(data, 4);
   cricket::SendDataResult result;
 
   // With rtp overhead of 32 bytes, each one of our packets is 36
@@ -410,7 +410,7 @@
     0x00, 0x00, 0x00, 0x00,
     'a', 'b', 'c', 'd', 'e'
   };
-  rtc::Buffer packet(data, sizeof(data));
+  rtc::CopyOnWriteBuffer packet(data, sizeof(data));
 
   std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
 
@@ -450,7 +450,7 @@
   unsigned char data[] = {
     0x80, 0x65, 0x00, 0x02
   };
-  rtc::Buffer packet(data, sizeof(data));
+  rtc::CopyOnWriteBuffer packet(data, sizeof(data));
 
   std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
 
diff --git a/webrtc/media/base/videoengine_unittest.h b/webrtc/media/base/videoengine_unittest.h
index f44e63a..10459db 100644
--- a/webrtc/media/base/videoengine_unittest.h
+++ b/webrtc/media/base/videoengine_unittest.h
@@ -258,28 +258,29 @@
   int NumSentSsrcs() {
     return network_interface_.NumSentSsrcs();
   }
-  const rtc::Buffer* GetRtpPacket(int index) {
+  const rtc::CopyOnWriteBuffer* GetRtpPacket(int index) {
     return network_interface_.GetRtpPacket(index);
   }
   int NumRtcpPackets() {
     return network_interface_.NumRtcpPackets();
   }
-  const rtc::Buffer* GetRtcpPacket(int index) {
+  const rtc::CopyOnWriteBuffer* GetRtcpPacket(int index) {
     return network_interface_.GetRtcpPacket(index);
   }
-  static int GetPayloadType(const rtc::Buffer* p) {
+  static int GetPayloadType(const rtc::CopyOnWriteBuffer* p) {
     int pt = -1;
     ParseRtpPacket(p, NULL, &pt, NULL, NULL, NULL, NULL);
     return pt;
   }
-  static bool ParseRtpPacket(const rtc::Buffer* p,
+  static bool ParseRtpPacket(const rtc::CopyOnWriteBuffer* p,
                              bool* x,
                              int* pt,
                              int* seqnum,
                              uint32_t* tstamp,
                              uint32_t* ssrc,
                              std::string* payload) {
-    rtc::ByteBuffer buf(*p);
+    // TODO(jbauch): avoid copying the buffer data into the ByteBuffer
+    rtc::ByteBuffer buf(p->data<char>(), p->size());
     uint8_t u08 = 0;
     uint16_t u16 = 0;
     uint32_t u32 = 0;
@@ -338,8 +339,9 @@
   bool CountRtcpFir(int start_index, int stop_index, int* fir_count) {
     int count = 0;
     for (int i = start_index; i < stop_index; ++i) {
-      std::unique_ptr<const rtc::Buffer> p(GetRtcpPacket(i));
-      rtc::ByteBuffer buf(*p);
+      std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtcpPacket(i));
+      // TODO(jbauch): avoid copying the buffer data into the ByteBuffer
+      rtc::ByteBuffer buf(p->data<char>(), p->size());
       size_t total_len = 0;
       // The packet may be a compound RTCP packet.
       while (total_len < p->size()) {
@@ -403,7 +405,7 @@
     EXPECT_TRUE(SetSend(true));
     EXPECT_TRUE(SendFrame());
     EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     EXPECT_EQ(codec.id, GetPayloadType(p.get()));
   }
   // Tests that we can send and receive frames.
@@ -414,7 +416,7 @@
     EXPECT_EQ(0, renderer_.num_rendered_frames());
     EXPECT_TRUE(SendFrame());
     EXPECT_FRAME_WAIT(1, codec.width, codec.height, kTimeout);
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     EXPECT_EQ(codec.id, GetPayloadType(p.get()));
   }
   void SendReceiveManyAndGetStats(const cricket::VideoCodec& codec,
@@ -429,7 +431,7 @@
         EXPECT_FRAME_WAIT(frame + i * fps, codec.width, codec.height, kTimeout);
       }
     }
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     EXPECT_EQ(codec.id, GetPayloadType(p.get()));
   }
 
@@ -622,7 +624,7 @@
     EXPECT_TRUE(SendFrame());
     EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
     uint32_t ssrc = 0;
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
     EXPECT_EQ(kSsrc, ssrc);
     // Packets are being paced out, so these can mismatch between the first and
@@ -645,7 +647,7 @@
     EXPECT_TRUE(WaitAndSendFrame(0));
     EXPECT_TRUE_WAIT(NumRtpPackets() > 0, kTimeout);
     uint32_t ssrc = 0;
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
     EXPECT_EQ(999u, ssrc);
     // Packets are being paced out, so these can mismatch between the first and
@@ -662,7 +664,7 @@
     uint8_t data1[] = {
         0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
 
-    rtc::Buffer packet1(data1, sizeof(data1));
+    rtc::CopyOnWriteBuffer packet1(data1, sizeof(data1));
     rtc::SetBE32(packet1.data() + 8, kSsrc);
     channel_->SetSink(kDefaultReceiveSsrc, NULL);
     EXPECT_TRUE(SetDefaultCodec());
@@ -695,7 +697,7 @@
     EXPECT_GT(NumRtpPackets(), 0);
     uint32_t ssrc = 0;
     size_t last_packet = NumRtpPackets() - 1;
-    std::unique_ptr<const rtc::Buffer>
+    std::unique_ptr<const rtc::CopyOnWriteBuffer>
         p(GetRtpPacket(static_cast<int>(last_packet)));
     ParseRtpPacket(p.get(), NULL, NULL, NULL, NULL, &ssrc, NULL);
     EXPECT_EQ(kSsrc, ssrc);
@@ -745,7 +747,7 @@
     EXPECT_FRAME_ON_RENDERER_WAIT(
         renderer2, 1, DefaultCodec().width, DefaultCodec().height, kTimeout);
 
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     EXPECT_EQ(DefaultCodec().id, GetPayloadType(p.get()));
     EXPECT_EQ(DefaultCodec().width, renderer1.width());
     EXPECT_EQ(DefaultCodec().height, renderer1.height());
@@ -1010,7 +1012,7 @@
     EXPECT_TRUE(WaitAndSendFrame(30));  // Should be rendered.
     frame_count += 2;
     EXPECT_FRAME_WAIT(frame_count, codec.width, codec.height, kTimeout);
-    std::unique_ptr<const rtc::Buffer> p(GetRtpPacket(0));
+    std::unique_ptr<const rtc::CopyOnWriteBuffer> p(GetRtpPacket(0));
     EXPECT_EQ(codec.id, GetPayloadType(p.get()));
 
     // The channel requires 15 fps.
diff --git a/webrtc/media/engine/webrtcvideoengine2.cc b/webrtc/media/engine/webrtcvideoengine2.cc
index 83f81f0..122edfe 100644
--- a/webrtc/media/engine/webrtcvideoengine2.cc
+++ b/webrtc/media/engine/webrtcvideoengine2.cc
@@ -14,7 +14,7 @@
 #include <set>
 #include <string>
 
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/stringutils.h"
 #include "webrtc/base/timeutils.h"
@@ -1300,14 +1300,14 @@
 }
 
 void WebRtcVideoChannel2::OnPacketReceived(
-    rtc::Buffer* packet,
+    rtc::CopyOnWriteBuffer* packet,
     const rtc::PacketTime& packet_time) {
   const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
                                               packet_time.not_before);
   const webrtc::PacketReceiver::DeliveryStatus delivery_result =
       call_->Receiver()->DeliverPacket(
           webrtc::MediaType::VIDEO,
-          reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
+          packet->cdata(), packet->size(),
           webrtc_packet_time);
   switch (delivery_result) {
     case webrtc::PacketReceiver::DELIVERY_OK:
@@ -1319,12 +1319,12 @@
   }
 
   uint32_t ssrc = 0;
-  if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
+  if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
     return;
   }
 
   int payload_type = 0;
-  if (!GetRtpPayloadType(packet->data(), packet->size(), &payload_type)) {
+  if (!GetRtpPayloadType(packet->cdata(), packet->size(), &payload_type)) {
     return;
   }
 
@@ -1350,7 +1350,7 @@
 
   if (call_->Receiver()->DeliverPacket(
           webrtc::MediaType::VIDEO,
-          reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
+          packet->cdata(), packet->size(),
           webrtc_packet_time) != webrtc::PacketReceiver::DELIVERY_OK) {
     LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
     return;
@@ -1358,7 +1358,7 @@
 }
 
 void WebRtcVideoChannel2::OnRtcpReceived(
-    rtc::Buffer* packet,
+    rtc::CopyOnWriteBuffer* packet,
     const rtc::PacketTime& packet_time) {
   const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
                                               packet_time.not_before);
@@ -1368,7 +1368,7 @@
   // logging failures spam the log).
   call_->Receiver()->DeliverPacket(
       webrtc::MediaType::VIDEO,
-      reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
+      packet->cdata(), packet->size(),
       webrtc_packet_time);
 }
 
@@ -1424,14 +1424,14 @@
 bool WebRtcVideoChannel2::SendRtp(const uint8_t* data,
                                   size_t len,
                                   const webrtc::PacketOptions& options) {
-  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
+  rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
   rtc::PacketOptions rtc_options;
   rtc_options.packet_id = options.packet_id;
   return MediaChannel::SendPacket(&packet, rtc_options);
 }
 
 bool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
-  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
+  rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
   return MediaChannel::SendRtcp(&packet, rtc::PacketOptions());
 }
 
diff --git a/webrtc/media/engine/webrtcvideoengine2.h b/webrtc/media/engine/webrtcvideoengine2.h
index 7ffd853..171f26a 100644
--- a/webrtc/media/engine/webrtcvideoengine2.h
+++ b/webrtc/media/engine/webrtcvideoengine2.h
@@ -163,9 +163,9 @@
   bool GetStats(VideoMediaInfo* info) override;
   bool SetCapturer(uint32_t ssrc, VideoCapturer* capturer) override;
 
-  void OnPacketReceived(rtc::Buffer* packet,
+  void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                         const rtc::PacketTime& packet_time) override;
-  void OnRtcpReceived(rtc::Buffer* packet,
+  void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                       const rtc::PacketTime& packet_time) override;
   void OnReadyToSend(bool ready) override;
   void SetInterface(NetworkInterface* iface) override;
diff --git a/webrtc/media/engine/webrtcvideoengine2_unittest.cc b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
index 64c691f..fc18721 100644
--- a/webrtc/media/engine/webrtcvideoengine2_unittest.cc
+++ b/webrtc/media/engine/webrtcvideoengine2_unittest.cc
@@ -2959,7 +2959,7 @@
   uint8_t data[kDataLength];
   memset(data, 0, sizeof(data));
   rtc::SetBE32(&data[8], ssrcs[0]);
-  rtc::Buffer packet(data, kDataLength);
+  rtc::CopyOnWriteBuffer packet(data, kDataLength);
   rtc::PacketTime packet_time;
   channel_->OnPacketReceived(&packet, packet_time);
 
@@ -3112,7 +3112,7 @@
 
   rtc::Set8(data, 1, payload_type);
   rtc::SetBE32(&data[8], kIncomingUnsignalledSsrc);
-  rtc::Buffer packet(data, kDataLength);
+  rtc::CopyOnWriteBuffer packet(data, kDataLength);
   rtc::PacketTime packet_time;
   channel_->OnPacketReceived(&packet, packet_time);
 
diff --git a/webrtc/media/engine/webrtcvoiceengine.cc b/webrtc/media/engine/webrtcvoiceengine.cc
index ae2518b..4f6ae43 100644
--- a/webrtc/media/engine/webrtcvoiceengine.cc
+++ b/webrtc/media/engine/webrtcvoiceengine.cc
@@ -2237,11 +2237,11 @@
 }
 
 void WebRtcVoiceMediaChannel::OnPacketReceived(
-    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
+    rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 
   uint32_t ssrc = 0;
-  if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
+  if (!GetRtpSsrc(packet->cdata(), packet->size(), &ssrc)) {
     return;
   }
 
@@ -2269,8 +2269,7 @@
                                               packet_time.not_before);
   webrtc::PacketReceiver::DeliveryStatus delivery_result =
       call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
-          reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
-          webrtc_packet_time);
+          packet->cdata(), packet->size(), webrtc_packet_time);
   if (webrtc::PacketReceiver::DELIVERY_OK != delivery_result) {
     // If the SSRC is unknown here, route it to the default channel, if we have
     // one. See: https://bugs.chromium.org/p/webrtc/issues/detail?id=5208
@@ -2288,26 +2287,25 @@
 
   // Pass it off to the decoder.
   engine()->voe()->network()->ReceivedRTPPacket(
-      channel, packet->data(), packet->size(), webrtc_packet_time);
+      channel, packet->cdata(), packet->size(), webrtc_packet_time);
 }
 
 void WebRtcVoiceMediaChannel::OnRtcpReceived(
-    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
+    rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
   RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
 
   // Forward packet to Call as well.
   const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
                                               packet_time.not_before);
   call_->Receiver()->DeliverPacket(webrtc::MediaType::AUDIO,
-      reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
-      webrtc_packet_time);
+      packet->cdata(), packet->size(), webrtc_packet_time);
 
   // Sending channels need all RTCP packets with feedback information.
   // Even sender reports can contain attached report blocks.
   // Receiving channels need sender reports in order to create
   // correct receiver reports.
   int type = 0;
-  if (!GetRtcpType(packet->data(), packet->size(), &type)) {
+  if (!GetRtcpType(packet->cdata(), packet->size(), &type)) {
     LOG(LS_WARNING) << "Failed to parse type from received RTCP packet";
     return;
   }
@@ -2315,13 +2313,13 @@
   // If it is a sender report, find the receive channel that is listening.
   if (type == kRtcpTypeSR) {
     uint32_t ssrc = 0;
-    if (!GetRtcpSsrc(packet->data(), packet->size(), &ssrc)) {
+    if (!GetRtcpSsrc(packet->cdata(), packet->size(), &ssrc)) {
       return;
     }
     int recv_channel_id = GetReceiveChannelId(ssrc);
     if (recv_channel_id != -1) {
       engine()->voe()->network()->ReceivedRTCPPacket(
-          recv_channel_id, packet->data(), packet->size());
+          recv_channel_id, packet->cdata(), packet->size());
     }
   }
 
@@ -2330,7 +2328,7 @@
   // will filter out RR internally.
   for (const auto& ch : send_streams_) {
     engine()->voe()->network()->ReceivedRTCPPacket(
-        ch.second->channel(), packet->data(), packet->size());
+        ch.second->channel(), packet->cdata(), packet->size());
   }
 }
 
diff --git a/webrtc/media/engine/webrtcvoiceengine.h b/webrtc/media/engine/webrtcvoiceengine.h
index 0ccc649..a16d042 100644
--- a/webrtc/media/engine/webrtcvoiceengine.h
+++ b/webrtc/media/engine/webrtcvoiceengine.h
@@ -179,9 +179,9 @@
   bool CanInsertDtmf() override;
   bool InsertDtmf(uint32_t ssrc, int event, int duration) override;
 
-  void OnPacketReceived(rtc::Buffer* packet,
+  void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                         const rtc::PacketTime& packet_time) override;
-  void OnRtcpReceived(rtc::Buffer* packet,
+  void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                       const rtc::PacketTime& packet_time) override;
   void OnReadyToSend(bool ready) override {}
   bool GetStats(VoiceMediaInfo* info) override;
@@ -194,16 +194,14 @@
   bool SendRtp(const uint8_t* data,
                size_t len,
                const webrtc::PacketOptions& options) override {
-    rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len,
-                       kMaxRtpPacketLen);
+    rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
     rtc::PacketOptions rtc_options;
     rtc_options.packet_id = options.packet_id;
     return VoiceMediaChannel::SendPacket(&packet, rtc_options);
   }
 
   bool SendRtcp(const uint8_t* data, size_t len) override {
-    rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len,
-                       kMaxRtpPacketLen);
+    rtc::CopyOnWriteBuffer packet(data, len, kMaxRtpPacketLen);
     return VoiceMediaChannel::SendRtcp(&packet, rtc::PacketOptions());
   }
 
diff --git a/webrtc/media/engine/webrtcvoiceengine_unittest.cc b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
index 4fd5918..b538c6f 100644
--- a/webrtc/media/engine/webrtcvoiceengine_unittest.cc
+++ b/webrtc/media/engine/webrtcvoiceengine_unittest.cc
@@ -113,7 +113,7 @@
     EXPECT_FALSE(call_.GetAudioSendStream(kSsrc1));
   }
   void DeliverPacket(const void* data, int len) {
-    rtc::Buffer packet(reinterpret_cast<const uint8_t*>(data), len);
+    rtc::CopyOnWriteBuffer packet(reinterpret_cast<const uint8_t*>(data), len);
     channel_->OnPacketReceived(&packet, rtc::PacketTime());
   }
   void TearDown() override {
@@ -3081,14 +3081,14 @@
 TEST_F(WebRtcVoiceEngineTestFake, DeliverAudioPacket_Call) {
   // Test that packets are forwarded to the Call when configured accordingly.
   const uint32_t kAudioSsrc = 1;
-  rtc::Buffer kPcmuPacket(kPcmuFrame, sizeof(kPcmuFrame));
+  rtc::CopyOnWriteBuffer kPcmuPacket(kPcmuFrame, sizeof(kPcmuFrame));
   static const unsigned char kRtcp[] = {
     0x80, 0xc9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02,
     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
   };
-  rtc::Buffer kRtcpPacket(kRtcp, sizeof(kRtcp));
+  rtc::CopyOnWriteBuffer kRtcpPacket(kRtcp, sizeof(kRtcp));
 
   EXPECT_TRUE(SetupEngineWithSendStream());
   cricket::WebRtcVoiceMediaChannel* media_channel =
diff --git a/webrtc/media/sctp/sctpdataengine.cc b/webrtc/media/sctp/sctpdataengine.cc
index ce0f91a..3ebc8de 100644
--- a/webrtc/media/sctp/sctpdataengine.cc
+++ b/webrtc/media/sctp/sctpdataengine.cc
@@ -19,7 +19,7 @@
 
 #include "usrsctplib/usrsctp.h"
 #include "webrtc/base/arraysize.h"
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/helpers.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/safe_conversions.h"
@@ -89,7 +89,7 @@
 
 namespace cricket {
 typedef rtc::ScopedMessageData<SctpInboundPacket> InboundPacketMessage;
-typedef rtc::ScopedMessageData<rtc::Buffer> OutboundPacketMessage;
+typedef rtc::ScopedMessageData<rtc::CopyOnWriteBuffer> OutboundPacketMessage;
 
 // The biggest SCTP packet.  Starting from a 'safe' wire MTU value of 1280,
 // take off 80 bytes for DTLS/TURN/TCP/IP overhead.
@@ -103,7 +103,7 @@
 };
 
 struct SctpInboundPacket {
-  rtc::Buffer buffer;
+  rtc::CopyOnWriteBuffer buffer;
   ReceiveDataParams params;
   // The |flags| parameter is used by SCTP to distinguish notification packets
   // from other types of packets.
@@ -165,7 +165,7 @@
 }
 
 // Log the packet in text2pcap format, if log level is at LS_VERBOSE.
-static void VerboseLogPacket(void *data, size_t length, int direction) {
+static void VerboseLogPacket(const void *data, size_t length, int direction) {
   if (LOG_CHECK_LEVEL(LS_VERBOSE) && length > 0) {
     char *dump_buf;
     if ((dump_buf = usrsctp_dumppacket(
@@ -189,7 +189,7 @@
   VerboseLogPacket(addr, length, SCTP_DUMP_OUTBOUND);
   // Note: We have to copy the data; the caller will delete it.
   auto* msg = new OutboundPacketMessage(
-      new rtc::Buffer(reinterpret_cast<uint8_t*>(data), length));
+      new rtc::CopyOnWriteBuffer(reinterpret_cast<uint8_t*>(data), length));
   channel->worker_thread()->Post(channel, MSG_SCTPOUTBOUNDPACKET, msg);
   return 0;
 }
@@ -581,7 +581,7 @@
 
 bool SctpDataMediaChannel::SendData(
     const SendDataParams& params,
-    const rtc::Buffer& payload,
+    const rtc::CopyOnWriteBuffer& payload,
     SendDataResult* result) {
   if (result) {
     // Preset |result| to assume an error.  If SendData succeeds, we'll
@@ -651,7 +651,7 @@
 
 // Called by network interface when a packet has been received.
 void SctpDataMediaChannel::OnPacketReceived(
-    rtc::Buffer* packet, const rtc::PacketTime& packet_time) {
+    rtc::CopyOnWriteBuffer* packet, const rtc::PacketTime& packet_time) {
   RTC_DCHECK(rtc::Thread::Current() == worker_thread_);
   LOG(LS_VERBOSE) << debug_name_ << "->OnPacketReceived(...): "
                   << " length=" << packet->size() << ", sending: " << sending_;
@@ -663,8 +663,8 @@
     // Pass received packet to SCTP stack. Once processed by usrsctp, the data
     // will be will be given to the global OnSctpInboundData, and then,
     // marshalled by a Post and handled with OnMessage.
-    VerboseLogPacket(packet->data(), packet->size(), SCTP_DUMP_INBOUND);
-    usrsctp_conninput(this, packet->data(), packet->size(), 0);
+    VerboseLogPacket(packet->cdata(), packet->size(), SCTP_DUMP_INBOUND);
+    usrsctp_conninput(this, packet->cdata(), packet->size(), 0);
   } else {
     // TODO(ldixon): Consider caching the packet for very slightly better
     // reliability.
@@ -686,25 +686,25 @@
     return;
   }
   if (packet->flags & MSG_NOTIFICATION) {
-    OnNotificationFromSctp(&packet->buffer);
+    OnNotificationFromSctp(packet->buffer);
   } else {
-    OnDataFromSctpToChannel(packet->params, &packet->buffer);
+    OnDataFromSctpToChannel(packet->params, packet->buffer);
   }
 }
 
 void SctpDataMediaChannel::OnDataFromSctpToChannel(
-    const ReceiveDataParams& params, rtc::Buffer* buffer) {
+    const ReceiveDataParams& params, const rtc::CopyOnWriteBuffer& buffer) {
   if (receiving_) {
     LOG(LS_VERBOSE) << debug_name_ << "->OnDataFromSctpToChannel(...): "
-                    << "Posting with length: " << buffer->size()
+                    << "Posting with length: " << buffer.size()
                     << " on stream " << params.ssrc;
     // Reports all received messages to upper layers, no matter whether the sid
     // is known.
-    SignalDataReceived(params, buffer->data<char>(), buffer->size());
+    SignalDataReceived(params, buffer.data<char>(), buffer.size());
   } else {
     LOG(LS_WARNING) << debug_name_ << "->OnDataFromSctpToChannel(...): "
                     << "Not receiving packet with sid=" << params.ssrc
-                    << " len=" << buffer->size() << " before SetReceive(true).";
+                    << " len=" << buffer.size() << " before SetReceive(true).";
   }
 }
 
@@ -767,10 +767,11 @@
   return true;
 }
 
-void SctpDataMediaChannel::OnNotificationFromSctp(rtc::Buffer* buffer) {
+void SctpDataMediaChannel::OnNotificationFromSctp(
+    const rtc::CopyOnWriteBuffer& buffer) {
   const sctp_notification& notification =
-      reinterpret_cast<const sctp_notification&>(*buffer->data());
-  ASSERT(notification.sn_header.sn_length == buffer->size());
+      reinterpret_cast<const sctp_notification&>(*buffer.data());
+  ASSERT(notification.sn_header.sn_length == buffer.size());
 
   // TODO(ldixon): handle notifications appropriately.
   switch (notification.sn_header.sn_type) {
@@ -963,7 +964,7 @@
 }
 
 void SctpDataMediaChannel::OnPacketFromSctpToNetwork(
-    rtc::Buffer* buffer) {
+    rtc::CopyOnWriteBuffer* buffer) {
   // usrsctp seems to interpret the MTU we give it strangely -- it seems to
   // give us back packets bigger than that MTU, if only by a fixed amount.
   // This is that amount that we've observed.
diff --git a/webrtc/media/sctp/sctpdataengine.h b/webrtc/media/sctp/sctpdataengine.h
index 310d974..8eb9956 100644
--- a/webrtc/media/sctp/sctpdataengine.h
+++ b/webrtc/media/sctp/sctpdataengine.h
@@ -24,7 +24,7 @@
 };
 }  // namespace cricket
 
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/media/base/codec.h"
 #include "webrtc/media/base/mediachannel.h"
 #include "webrtc/media/base/mediaengine.h"
@@ -144,10 +144,10 @@
   // sctp that will then post the network interface by OnMessage).
   // Returns true iff successful data somewhere on the send-queue/network.
   virtual bool SendData(const SendDataParams& params,
-                        const rtc::Buffer& payload,
+                        const rtc::CopyOnWriteBuffer& payload,
                         SendDataResult* result = NULL);
   // A packet is received from the network interface. Posted to OnMessage.
-  virtual void OnPacketReceived(rtc::Buffer* packet,
+  virtual void OnPacketReceived(rtc::CopyOnWriteBuffer* packet,
                                 const rtc::PacketTime& packet_time);
 
   // Exposed to allow Post call from c-callbacks.
@@ -155,7 +155,7 @@
 
   // Many of these things are unused by SCTP, but are needed to fulfill
   // the MediaChannel interface.
-  virtual void OnRtcpReceived(rtc::Buffer* packet,
+  virtual void OnRtcpReceived(rtc::CopyOnWriteBuffer* packet,
                               const rtc::PacketTime& packet_time) {}
   virtual void OnReadyToSend(bool ready) {}
 
@@ -192,12 +192,12 @@
   bool ResetStream(uint32_t ssrc);
 
   // Called by OnMessage to send packet on the network.
-  void OnPacketFromSctpToNetwork(rtc::Buffer* buffer);
+  void OnPacketFromSctpToNetwork(rtc::CopyOnWriteBuffer* buffer);
   // Called by OnMessage to decide what to do with the packet.
   void OnInboundPacketFromSctpToChannel(SctpInboundPacket* packet);
   void OnDataFromSctpToChannel(const ReceiveDataParams& params,
-                               rtc::Buffer* buffer);
-  void OnNotificationFromSctp(rtc::Buffer* buffer);
+                               const rtc::CopyOnWriteBuffer& buffer);
+  void OnNotificationFromSctp(const rtc::CopyOnWriteBuffer& buffer);
   void OnNotificationAssocChange(const sctp_assoc_change& change);
 
   void OnStreamResetEvent(const struct sctp_stream_reset_event* evt);
diff --git a/webrtc/media/sctp/sctpdataengine_unittest.cc b/webrtc/media/sctp/sctpdataengine_unittest.cc
index 893d717..f18437d 100644
--- a/webrtc/media/sctp/sctpdataengine_unittest.cc
+++ b/webrtc/media/sctp/sctpdataengine_unittest.cc
@@ -17,7 +17,7 @@
 #include <vector>
 
 #include "webrtc/base/bind.h"
-#include "webrtc/base/buffer.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/gunit.h"
 #include "webrtc/base/helpers.h"
@@ -47,13 +47,11 @@
 
  protected:
   // Called to send raw packet down the wire (e.g. SCTP an packet).
-  virtual bool SendPacket(rtc::Buffer* packet,
+  virtual bool SendPacket(rtc::CopyOnWriteBuffer* packet,
                           const rtc::PacketOptions& options) {
     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::SendPacket";
 
-    // TODO(ldixon): Can/should we use Buffer.TransferTo here?
-    // Note: this assignment does a deep copy of data from packet.
-    rtc::Buffer* buffer = new rtc::Buffer(packet->data(), packet->size());
+    rtc::CopyOnWriteBuffer* buffer = new rtc::CopyOnWriteBuffer(*packet);
     thread_->Post(this, MSG_PACKET, rtc::WrapMessageData(buffer));
     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::SendPacket, Posted message.";
     return true;
@@ -64,8 +62,8 @@
   // an SCTP packet.
   virtual void OnMessage(rtc::Message* msg) {
     LOG(LS_VERBOSE) << "SctpFakeNetworkInterface::OnMessage";
-    std::unique_ptr<rtc::Buffer> buffer(
-        static_cast<rtc::TypedMessageData<rtc::Buffer*>*>(
+    std::unique_ptr<rtc::CopyOnWriteBuffer> buffer(
+        static_cast<rtc::TypedMessageData<rtc::CopyOnWriteBuffer*>*>(
             msg->pdata)->data());
     if (dest_) {
       dest_->OnPacketReceived(buffer.get(), rtc::PacketTime());
@@ -76,7 +74,7 @@
   // Unsupported functions required to exist by NetworkInterface.
   // TODO(ldixon): Refactor parent NetworkInterface class so these are not
   // required. They are RTC specific and should be in an appropriate subclass.
-  virtual bool SendRtcp(rtc::Buffer* packet,
+  virtual bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
                         const rtc::PacketOptions& options) {
     LOG(LS_WARNING) << "Unsupported: SctpFakeNetworkInterface::SendRtcp.";
     return false;
@@ -283,7 +281,7 @@
     cricket::SendDataParams params;
     params.ssrc = ssrc;
 
-    return chan->SendData(params, rtc::Buffer(
+    return chan->SendData(params, rtc::CopyOnWriteBuffer(
         &msg[0], msg.length()), result);
   }
 
@@ -402,7 +400,7 @@
 
   for (size_t i = 0; i < 100; ++i) {
     channel1()->SendData(
-        params, rtc::Buffer(&buffer[0], buffer.size()), &result);
+        params, rtc::CopyOnWriteBuffer(&buffer[0], buffer.size()), &result);
     if (result == cricket::SDR_BLOCK)
       break;
   }
diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc
index d9aa851..8e916f1 100644
--- a/webrtc/pc/channel.cc
+++ b/webrtc/pc/channel.cc
@@ -14,9 +14,9 @@
 
 #include "webrtc/audio_sink.h"
 #include "webrtc/base/bind.h"
-#include "webrtc/base/buffer.h"
 #include "webrtc/base/byteorder.h"
 #include "webrtc/base/common.h"
+#include "webrtc/base/copyonwritebuffer.h"
 #include "webrtc/base/dscp.h"
 #include "webrtc/base/logging.h"
 #include "webrtc/base/trace_event.h"
@@ -61,7 +61,7 @@
 }
 
 struct PacketMessageData : public rtc::MessageData {
-  rtc::Buffer packet;
+  rtc::CopyOnWriteBuffer packet;
   rtc::PacketOptions options;
 };
 
@@ -93,7 +93,7 @@
   return (!rtcp) ? "RTP" : "RTCP";
 }
 
-static bool ValidPacket(bool rtcp, const rtc::Buffer* packet) {
+static bool ValidPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
   // Check the packet size. We could check the header too if needed.
   return (packet &&
           packet->size() >= (!rtcp ? kMinRtpPacketLen : kMinRtcpPacketLen) &&
@@ -435,12 +435,12 @@
          (srtp_filter_.IsActive() || !ShouldSetupDtlsSrtp());
 }
 
-bool BaseChannel::SendPacket(rtc::Buffer* packet,
+bool BaseChannel::SendPacket(rtc::CopyOnWriteBuffer* packet,
                              const rtc::PacketOptions& options) {
   return SendPacket(false, packet, options);
 }
 
-bool BaseChannel::SendRtcp(rtc::Buffer* packet,
+bool BaseChannel::SendRtcp(rtc::CopyOnWriteBuffer* packet,
                            const rtc::PacketOptions& options) {
   return SendPacket(true, packet, options);
 }
@@ -479,7 +479,7 @@
   // When using RTCP multiplexing we might get RTCP packets on the RTP
   // transport. We feed RTP traffic into the demuxer to determine if it is RTCP.
   bool rtcp = PacketIsRtcp(channel, data, len);
-  rtc::Buffer packet(data, len);
+  rtc::CopyOnWriteBuffer packet(data, len);
   HandlePacket(rtcp, &packet, packet_time);
 }
 
@@ -529,7 +529,7 @@
 }
 
 bool BaseChannel::SendPacket(bool rtcp,
-                             rtc::Buffer* packet,
+                             rtc::CopyOnWriteBuffer* packet,
                              const rtc::PacketOptions& options) {
   // SendPacket gets called from MediaEngine, typically on an encoder thread.
   // If the thread is not our worker thread, we will post to our worker
@@ -650,7 +650,7 @@
   return true;
 }
 
-bool BaseChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
+bool BaseChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
   // Protect ourselves against crazy data.
   if (!ValidPacket(rtcp, packet)) {
     LOG(LS_ERROR) << "Dropping incoming " << content_name_ << " "
@@ -663,10 +663,10 @@
     return true;
   }
   // Check whether we handle this payload.
-  return bundle_filter_.DemuxPacket(packet->data<uint8_t>(), packet->size());
+  return bundle_filter_.DemuxPacket(packet->data(), packet->size());
 }
 
-void BaseChannel::HandlePacket(bool rtcp, rtc::Buffer* packet,
+void BaseChannel::HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
                                const rtc::PacketTime& packet_time) {
   if (!WantsPacket(rtcp, packet)) {
     return;
@@ -1908,7 +1908,7 @@
 }
 
 bool DataChannel::SendData(const SendDataParams& params,
-                           const rtc::Buffer& payload,
+                           const rtc::CopyOnWriteBuffer& payload,
                            SendDataResult* result) {
   return InvokeOnWorker(Bind(&DataMediaChannel::SendData,
                              media_channel(), params, payload, result));
@@ -1919,7 +1919,7 @@
   return GetFirstDataContent(sdesc);
 }
 
-bool DataChannel::WantsPacket(bool rtcp, rtc::Buffer* packet) {
+bool DataChannel::WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet) {
   if (data_channel_type_ == DCT_SCTP) {
     // TODO(pthatcher): Do this in a more robust way by checking for
     // SCTP or DTLS.
diff --git a/webrtc/pc/channel.h b/webrtc/pc/channel.h
index 1937b04..45657f8 100644
--- a/webrtc/pc/channel.h
+++ b/webrtc/pc/channel.h
@@ -191,10 +191,10 @@
   void FlushRtcpMessages();
 
   // NetworkInterface implementation, called by MediaEngine
-  bool SendPacket(rtc::Buffer* packet,
-                          const rtc::PacketOptions& options) override;
-  bool SendRtcp(rtc::Buffer* packet, const rtc::PacketOptions& options)
-      override;
+  bool SendPacket(rtc::CopyOnWriteBuffer* packet,
+                  const rtc::PacketOptions& options) override;
+  bool SendRtcp(rtc::CopyOnWriteBuffer* packet,
+                const rtc::PacketOptions& options) override;
 
   // From TransportChannel
   void OnWritableState(TransportChannel* channel);
@@ -210,10 +210,10 @@
   bool PacketIsRtcp(const TransportChannel* channel, const char* data,
                     size_t len);
   bool SendPacket(bool rtcp,
-                  rtc::Buffer* packet,
+                  rtc::CopyOnWriteBuffer* packet,
                   const rtc::PacketOptions& options);
-  virtual bool WantsPacket(bool rtcp, rtc::Buffer* packet);
-  void HandlePacket(bool rtcp, rtc::Buffer* packet,
+  virtual bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
+  void HandlePacket(bool rtcp, rtc::CopyOnWriteBuffer* packet,
                     const rtc::PacketTime& packet_time);
 
   void EnableMedia_w();
@@ -502,7 +502,7 @@
   bool Init();
 
   virtual bool SendData(const SendDataParams& params,
-                        const rtc::Buffer& payload,
+                        const rtc::CopyOnWriteBuffer& payload,
                         SendDataResult* result);
 
   void StartMediaMonitor(int cms);
@@ -516,8 +516,8 @@
   sigslot::signal2<DataChannel*, const DataMediaInfo&> SignalMediaMonitor;
   sigslot::signal2<DataChannel*, const std::vector<ConnectionInfo>&>
       SignalConnectionMonitor;
-  sigslot::signal3<DataChannel*, const ReceiveDataParams&, const rtc::Buffer&>
-      SignalDataReceived;
+  sigslot::signal3<DataChannel*, const ReceiveDataParams&,
+      const rtc::CopyOnWriteBuffer&> SignalDataReceived;
   // Signal for notifying when the channel becomes ready to send data.
   // That occurs when the channel is enabled, the transport is writable,
   // both local and remote descriptions are set, and the channel is unblocked.
@@ -534,7 +534,7 @@
  private:
   struct SendDataMessageData : public rtc::MessageData {
     SendDataMessageData(const SendDataParams& params,
-                        const rtc::Buffer* payload,
+                        const rtc::CopyOnWriteBuffer* payload,
                         SendDataResult* result)
         : params(params),
           payload(payload),
@@ -543,7 +543,7 @@
     }
 
     const SendDataParams& params;
-    const rtc::Buffer* payload;
+    const rtc::CopyOnWriteBuffer* payload;
     SendDataResult* result;
     bool succeeded;
   };
@@ -558,7 +558,7 @@
           payload(data, len) {
     }
     const ReceiveDataParams params;
-    const rtc::Buffer payload;
+    const rtc::CopyOnWriteBuffer payload;
   };
 
   typedef rtc::TypedMessageData<bool> DataChannelReadyToSendMessageData;
@@ -581,7 +581,7 @@
                                   ContentAction action,
                                   std::string* error_desc);
   virtual void ChangeState();
-  virtual bool WantsPacket(bool rtcp, rtc::Buffer* packet);
+  virtual bool WantsPacket(bool rtcp, const rtc::CopyOnWriteBuffer* packet);
 
   virtual void OnMessage(rtc::Message* pmsg);
   virtual void GetSrtpCryptoSuites(std::vector<int>* crypto_suites) const;
diff --git a/webrtc/pc/channel_unittest.cc b/webrtc/pc/channel_unittest.cc
index 686f85d..ecbdad4 100644
--- a/webrtc/pc/channel_unittest.cc
+++ b/webrtc/pc/channel_unittest.cc
@@ -2769,7 +2769,7 @@
   unsigned char data[] = {
     'f', 'o', 'o'
   };
-  rtc::Buffer payload(data, 3);
+  rtc::CopyOnWriteBuffer payload(data, 3);
   cricket::SendDataResult result;
   ASSERT_TRUE(media_channel1_->SendData(params, payload, &result));
   EXPECT_EQ(params.ssrc,