Avoid Realloc in LibvpxVp8Encoder

Instead, compute the needed buffer size for the encoded VP8 frame
prior to copying the data.

Bug: chromium:1012256
Change-Id: I3dda921f6d8f974731d2138bc5f6166cfdb9a321
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/157303
Commit-Queue: Niels Moller <nisse@webrtc.org>
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29531}
diff --git a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
index 556ac60..42d13a0 100644
--- a/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
+++ b/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
@@ -1131,19 +1131,28 @@
     CodecSpecificInfo codec_specific;
     const vpx_codec_cx_pkt_t* pkt = NULL;
 
+    size_t encoded_size = 0;
+    while ((pkt = libvpx_->codec_get_cx_data(&encoders_[encoder_idx], &iter)) !=
+           NULL) {
+      if (pkt->kind == VPX_CODEC_CX_FRAME_PKT) {
+        encoded_size += pkt->data.frame.sz;
+      }
+    }
+
     // TODO(nisse): Introduce some buffer cache or buffer pool, to reduce
     // allocations and/or copy operations.
-    auto buffer = EncodedImageBuffer::Create();
+    auto buffer = EncodedImageBuffer::Create(encoded_size);
 
+    iter = NULL;
+    size_t encoded_pos = 0;
     while ((pkt = libvpx_->codec_get_cx_data(&encoders_[encoder_idx], &iter)) !=
            NULL) {
       switch (pkt->kind) {
         case VPX_CODEC_CX_FRAME_PKT: {
-          const size_t size = buffer->size();
-          const size_t new_size = pkt->data.frame.sz + size;
-          buffer->Realloc(new_size);
-          memcpy(&buffer->data()[size], pkt->data.frame.buf,
+          RTC_CHECK_LE(encoded_pos + pkt->data.frame.sz, buffer->size());
+          memcpy(&buffer->data()[encoded_pos], pkt->data.frame.buf,
                  pkt->data.frame.sz);
+          encoded_pos += pkt->data.frame.sz;
           break;
         }
         default:
@@ -1157,6 +1166,7 @@
               VideoFrameType::kVideoFrameKey;
         }
         encoded_images_[encoder_idx].SetEncodedData(buffer);
+        encoded_images_[encoder_idx].set_size(encoded_pos);
         encoded_images_[encoder_idx].SetSpatialIndex(stream_idx);
         PopulateCodecSpecific(&codec_specific, *pkt, stream_idx, encoder_idx,
                               input_image.timestamp());