10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2011 Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/videoframe.h"
290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
30b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org#include <string.h>
310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV)
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "libyuv/compare.h"
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "libyuv/planar_functions.h"
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "libyuv/scale.h"
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/videocommon.h"
39cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "webrtc/base/logging.h"
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Round to 2 pixels because Chroma channels are half size.
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#define ROUNDTO2(v) (v & ~1)
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgrtc::StreamResult VideoFrame::Write(rtc::StreamInterface* stream,
470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                          int* error) {
482a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::StreamResult result = rtc::SR_SUCCESS;
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_y = GetYPlane();
500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_u = GetUPlane();
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_v = GetVPlane();
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!src_y || !src_u || !src_v) {
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return result;  // Nothing to write.
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const int32 y_pitch = GetYPitch();
560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const int32 u_pitch = GetUPitch();
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const int32 v_pitch = GetVPitch();
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const size_t width = GetWidth();
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const size_t height = GetHeight();
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const size_t half_width = (width + 1) >> 1;
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const size_t half_height = (height + 1) >> 1;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Write Y.
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t row = 0; row < height; ++row) {
640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    result = stream->Write(src_y + row * y_pitch, width, NULL, error);
652a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (result != rtc::SR_SUCCESS) {
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return result;
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Write U.
700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t row = 0; row < half_height; ++row) {
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    result = stream->Write(src_u + row * u_pitch, half_width, NULL, error);
722a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (result != rtc::SR_SUCCESS) {
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return result;
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Write V.
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t row = 0; row < half_height; ++row) {
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    result = stream->Write(src_v + row * v_pitch, half_width, NULL, error);
792a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    if (result != rtc::SR_SUCCESS) {
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return result;
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return result;
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoFrame::CopyToPlanes(
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8* dst_y, uint8* dst_u, uint8* dst_v,
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int32 dst_pitch_y, int32 dst_pitch_u, int32 dst_pitch_v) const {
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV)
901a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  int32 src_width = static_cast<int>(GetWidth());
911a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  int32 src_height = static_cast<int>(GetHeight());
920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return libyuv::I420Copy(GetYPlane(), GetYPitch(),
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          GetUPlane(), GetUPitch(),
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          GetVPlane(), GetVPitch(),
950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          dst_y, dst_pitch_y,
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          dst_u, dst_pitch_u,
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          dst_v, dst_pitch_v,
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          src_width, src_height) == 0;
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int uv_size = GetUPitch() * GetChromaHeight();
1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memcpy(dst_y, GetYPlane(), GetWidth() * GetHeight());
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memcpy(dst_u, GetUPlane(), uv_size);
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memcpy(dst_v, GetVPlane(), uv_size);
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoFrame::CopyToFrame(VideoFrame* dst) const {
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dst) {
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "NULL dst pointer.";
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  CopyToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(),
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org               dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch());
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO(fbarchard): Handle odd width/height with rounding.
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoFrame::StretchToPlanes(
1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8* dst_y, uint8* dst_u, uint8* dst_v,
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int32 dst_pitch_y, int32 dst_pitch_u, int32 dst_pitch_v,
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    size_t width, size_t height, bool interpolate, bool vert_crop) const {
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!GetYPlane() || !GetUPlane() || !GetVPlane()) {
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "NULL plane pointer.";
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t src_width = GetWidth();
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t src_height = GetHeight();
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (width == src_width && height == src_height) {
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    CopyToPlanes(dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v);
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_y = GetYPlane();
1350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_u = GetUPlane();
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const uint8* src_v = GetVPlane();
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (vert_crop) {
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Adjust the input width:height ratio to be the same as the output ratio.
1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (src_width * height > src_height * width) {
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Reduce the input width, but keep size/position aligned for YuvScaler
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_width = ROUNDTO2(src_height * width / height);
1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      int32 iwidth_offset = ROUNDTO2((GetWidth() - src_width) / 2);
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_y += iwidth_offset;
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_u += iwidth_offset / 2;
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_v += iwidth_offset / 2;
1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (src_width * height < src_height * width) {
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      // Reduce the input height.
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_height = src_width * height / width;
1501a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org      int32 iheight_offset = static_cast<int32>(
1511a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org          (GetHeight() - src_height) >> 2);
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      iheight_offset <<= 1;  // Ensure that iheight_offset is even.
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_y += iheight_offset * GetYPitch();
1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_u += iheight_offset / 2 * GetUPitch();
1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      src_v += iheight_offset / 2 * GetVPitch();
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO(fbarchard): Implement a simple scale for non-libyuv.
1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV)
1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Scale to the output I420 frame.
1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  libyuv::Scale(src_y, src_u, src_v,
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                GetYPitch(), GetUPitch(), GetVPitch(),
1641a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                static_cast<int>(src_width), static_cast<int>(src_height),
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v,
1661a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                static_cast<int>(width), static_cast<int>(height), interpolate);
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgsize_t VideoFrame::StretchToBuffer(size_t dst_width, size_t dst_height,
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   uint8* dst_buffer, size_t size,
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   bool interpolate, bool vert_crop) const {
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dst_buffer) {
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "NULL dst_buffer pointer.";
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return 0;
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t needed = SizeOf(dst_width, dst_height);
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (needed <= size) {
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8* dst_y = dst_buffer;
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8* dst_u = dst_y + dst_width * dst_height;
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    uint8* dst_v = dst_u + ((dst_width + 1) >> 1) * ((dst_height + 1) >> 1);
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    StretchToPlanes(dst_y, dst_u, dst_v,
1841a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                    static_cast<int32>(dst_width),
1851a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                    static_cast<int32>((dst_width + 1) >> 1),
1861a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                    static_cast<int32>((dst_width + 1) >> 1),
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    dst_width, dst_height, interpolate, vert_crop);
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return needed;
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoFrame::StretchToFrame(VideoFrame* dst,
1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                bool interpolate, bool vert_crop) const {
1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!dst) {
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "NULL dst pointer.";
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StretchToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(),
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch(),
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  dst->GetWidth(), dst->GetHeight(),
2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  interpolate, vert_crop);
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dst->SetElapsedTime(GetElapsedTime());
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  dst->SetTimeStamp(GetTimeStamp());
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgVideoFrame* VideoFrame::Stretch(size_t dst_width, size_t dst_height,
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                bool interpolate, bool vert_crop) const {
2091a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  VideoFrame* dest = CreateEmptyFrame(static_cast<int>(dst_width),
2101a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                                      static_cast<int>(dst_height),
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      GetPixelWidth(), GetPixelHeight(),
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                      GetElapsedTime(), GetTimeStamp());
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (dest) {
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    StretchToFrame(dest, interpolate, vert_crop);
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return dest;
2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoFrame::SetToBlack() {
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV)
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return libyuv::I420Rect(GetYPlane(), GetYPitch(),
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          GetUPlane(), GetUPitch(),
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          GetVPlane(), GetVPitch(),
2241a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                          0, 0,
2251a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                          static_cast<int>(GetWidth()),
2261a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org                          static_cast<int>(GetHeight()),
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          16, 128, 128) == 0;
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#else
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int uv_size = GetUPitch() * GetChromaHeight();
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memset(GetYPlane(), 16, GetWidth() * GetHeight());
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memset(GetUPlane(), 128, uv_size);
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  memset(GetVPlane(), 128, uv_size);
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const size_t kMaxSampleSize = 1000000000u;
23883f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com// Returns whether a sample is valid.
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoFrame::Validate(uint32 fourcc, int w, int h,
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                          const uint8 *sample, size_t sample_size) {
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (h < 0) {
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    h = -h;
2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 16384 is maximum resolution for VP8 codec.
2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (w < 1 || w > 16384 || h < 1 || h > 16384) {
2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h;
2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 format = CanonicalFourCC(fourcc);
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int expected_bpp = 8;
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  switch (format) {
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_I400:
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_RGGB:
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_BGGR:
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_GRBG:
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_GBRG:
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 8;
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_I420:
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_I411:
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_YU12:
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_YV12:
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_M420:
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_Q420:
2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_NV21:
2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_NV12:
2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 12;
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_I422:
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_YV16:
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_YUY2:
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_UYVY:
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_RGBP:
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_RGBO:
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_R444:
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 16;
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_I444:
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_YV24:
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_24BG:
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_RAW:
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 24;
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_ABGR:
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_BGRA:
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_ARGB:
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 32;
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_MJPG:
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    case FOURCC_H264:
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 0;
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    default:
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      expected_bpp = 8;  // Expect format is at least 8 bits per pixel.
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t expected_size = (w * expected_bpp + 7) / 8 * h;
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // For compressed formats, expect 4 bits per 16 x 16 macro.  I420 would be
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // 6 bits, but grey can be 4 bits.
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (expected_bpp == 0) {
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    expected_size = ((w + 15) / 16) * ((h + 15) / 16) * 4 / 8;
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sample == NULL) {
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "NULL sample pointer."
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " format: " << GetFourccName(format)
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " bpp: " << expected_bpp
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " size: " << w << "x" << h
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " expected: " << expected_size
3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " " << sample_size;
3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
31483f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  // TODO(fbarchard): Make function to dump information about frames.
31583f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  uint8 four_samples[4] = { 0, 0, 0, 0 };
31683f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  for (size_t i = 0; i < ARRAY_SIZE(four_samples) && i < sample_size; ++i) {
31783f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com    four_samples[i] = sample[i];
31883f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  }
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sample_size < expected_size) {
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_ERROR) << "Size field is too small."
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " format: " << GetFourccName(format)
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " bpp: " << expected_bpp
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " size: " << w << "x" << h
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " " << sample_size
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                  << " expected: " << expected_size
32683f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                  << " sample[0..3]: " << static_cast<int>(four_samples[0])
32783f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                  << ", " << static_cast<int>(four_samples[1])
32883f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                  << ", " << static_cast<int>(four_samples[2])
32983f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                  << ", " << static_cast<int>(four_samples[3]);
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sample_size > kMaxSampleSize) {
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Size field is invalid."
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " format: " << GetFourccName(format)
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " bpp: " << expected_bpp
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " size: " << w << "x" << h
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " " << sample_size
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " expected: " << 2 * expected_size
33983f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << " sample[0..3]: " << static_cast<int>(four_samples[0])
34083f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[1])
34183f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[2])
34283f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[3]);
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Show large size warning once every 100 frames.
34683f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  // TODO(fbarchard): Make frame counter atomic for thread safety.
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  static int large_warn100 = 0;
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t large_expected_size = expected_size * 2;
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (expected_bpp >= 8 &&
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (sample_size > large_expected_size || sample_size > kMaxSampleSize) &&
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      large_warn100 % 100 == 0) {
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ++large_warn100;
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Size field is too large."
3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " format: " << GetFourccName(format)
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " bpp: " << expected_bpp
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " size: " << w << "x" << h
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " bytes: " << sample_size
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                    << " expected: " << large_expected_size
35983f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << " sample[0..3]: " << static_cast<int>(four_samples[0])
36083f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[1])
36183f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[2])
36283f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                    << ", " << static_cast<int>(four_samples[3]);
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
36583f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  // TODO(fbarchard): Add duplicate pixel check.
36683f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com  // TODO(fbarchard): Use frame counter atomic for thread safety.
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  static bool valid_once = true;
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (valid_once) {
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    valid_once = false;
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_INFO) << "Validate frame passed."
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " format: " << GetFourccName(format)
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " bpp: " << expected_bpp
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " size: " << w << "x" << h
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " bytes: " << sample_size
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 << " expected: " << expected_size
37683f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                 << " sample[0..3]: " << static_cast<int>(four_samples[0])
37783f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                 << ", " << static_cast<int>(four_samples[1])
37883f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                 << ", " << static_cast<int>(four_samples[2])
37983f8ee6dd17f3ab7429429601870f5792b82661ffbarchard@google.com                 << ", " << static_cast<int>(four_samples[3]);
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return true;
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
385