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