128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * libjingle 328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Copyright 2011 Google Inc. 428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer. 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * and/or other materials provided with the distribution. 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * derived from this software without specific prior written permission. 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/base/videoframe.h" 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30371243dfa3467c7be7217da4b537cc33d2bd45a6pbos@webrtc.org#include <string.h> 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "libyuv/compare.h" 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "libyuv/planar_functions.h" 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "libyuv/scale.h" 3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/base/videocommon.h" 365237aaf243d29732f59557361b7a993c0a18cf0etfarina#include "webrtc/base/arraysize.h" 37afdd5dd372d69be7244a3d90d70de9d5ecd60eb9magjed@webrtc.org#include "webrtc/base/checks.h" 38a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h" 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket { 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Round to 2 pixels because Chroma channels are half size. 4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#define ROUNDTO2(v) (v & ~1) 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 45d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgrtc::StreamResult VideoFrame::Write(rtc::StreamInterface* stream, 46f09e7b8a4f521447ea56e3e8c5ff2f6826feacf2magjed@webrtc.org int* error) const { 47d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::StreamResult result = rtc::SR_SUCCESS; 480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_y = GetYPlane(); 490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_u = GetUPlane(); 500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_v = GetVPlane(); 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!src_y || !src_u || !src_v) { 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return result; // Nothing to write. 5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const int32_t y_pitch = GetYPitch(); 550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const int32_t u_pitch = GetUPitch(); 560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const int32_t v_pitch = GetVPitch(); 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const size_t width = GetWidth(); 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const size_t height = GetHeight(); 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const size_t half_width = (width + 1) >> 1; 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const size_t half_height = (height + 1) >> 1; 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Write Y. 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t row = 0; row < height; ++row) { 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org result = stream->Write(src_y + row * y_pitch, width, NULL, error); 64d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org if (result != rtc::SR_SUCCESS) { 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return result; 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Write U. 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t row = 0; row < half_height; ++row) { 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org result = stream->Write(src_u + row * u_pitch, half_width, NULL, error); 71d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org if (result != rtc::SR_SUCCESS) { 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return result; 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Write V. 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t row = 0; row < half_height; ++row) { 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org result = stream->Write(src_v + row * v_pitch, half_width, NULL, error); 78d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org if (result != rtc::SR_SUCCESS) { 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return result; 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return result; 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmsize_t VideoFrame::CopyToBuffer(uint8_t* buffer, size_t size) const { 863864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org const size_t y_size = GetHeight() * GetYPitch(); 873864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org const size_t u_size = GetUPitch() * GetChromaHeight(); 883864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org const size_t v_size = GetVPitch() * GetChromaHeight(); 893864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org const size_t needed = y_size + u_size + v_size; 903864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org if (size < needed) 913864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org return needed; 923864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org CopyToPlanes(buffer, buffer + y_size, buffer + y_size + u_size, 933864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org GetYPitch(), GetUPitch(), GetVPitch()); 943864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org return needed; 953864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org} 963864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org 970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool VideoFrame::CopyToPlanes(uint8_t* dst_y, 980c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t* dst_u, 990c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t* dst_v, 1000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_y, 1010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_u, 1020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_v) const { 1033864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { 1043864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org LOG(LS_ERROR) << "NULL plane pointer."; 1053864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org return false; 1063864363e2c3043bd23081abe32ad13dcb6d718edmagjed@webrtc.org } 1070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t src_width = static_cast<int>(GetWidth()); 1080c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t src_height = static_cast<int>(GetHeight()); 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return libyuv::I420Copy(GetYPlane(), GetYPitch(), 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetUPlane(), GetUPitch(), 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetVPlane(), GetVPitch(), 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst_y, dst_pitch_y, 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst_u, dst_pitch_u, 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst_v, dst_pitch_v, 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_width, src_height) == 0; 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid VideoFrame::CopyToFrame(VideoFrame* dst) const { 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!dst) { 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "NULL dst pointer."; 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CopyToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(), 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch()); 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 1280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmsize_t VideoFrame::ConvertToRgbBuffer(uint32_t to_fourcc, 1290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t* buffer, 130bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org size_t size, 131bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org int stride_rgb) const { 132bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org const size_t needed = std::abs(stride_rgb) * GetHeight(); 133bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org if (size < needed) { 134bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org LOG(LS_WARNING) << "RGB buffer is not large enough"; 135bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org return needed; 136bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org } 137bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org 138bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org if (libyuv::ConvertFromI420(GetYPlane(), GetYPitch(), GetUPlane(), 139bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org GetUPitch(), GetVPlane(), GetVPitch(), buffer, 140bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org stride_rgb, static_cast<int>(GetWidth()), 141bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org static_cast<int>(GetHeight()), to_fourcc)) { 142bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org LOG(LS_ERROR) << "RGB type not supported: " << to_fourcc; 143bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org return 0; // 0 indicates error 144bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org } 145bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org return needed; 146bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org} 147bdcf38c89446b1b464a646414f6cd7573a190bd1magjed@webrtc.org 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// TODO(fbarchard): Handle odd width/height with rounding. 1490c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmvoid VideoFrame::StretchToPlanes(uint8_t* dst_y, 1500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t* dst_u, 1510c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t* dst_v, 1520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_y, 1530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_u, 1540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t dst_pitch_v, 1550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström size_t width, 1560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström size_t height, 1570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström bool interpolate, 1580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström bool vert_crop) const { 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!GetYPlane() || !GetUPlane() || !GetVPlane()) { 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "NULL plane pointer."; 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t src_width = GetWidth(); 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t src_height = GetHeight(); 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (width == src_width && height == src_height) { 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org CopyToPlanes(dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v); 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 1700c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_y = GetYPlane(); 1710c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_u = GetUPlane(); 1720c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* src_v = GetVPlane(); 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (vert_crop) { 17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Adjust the input width:height ratio to be the same as the output ratio. 17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (src_width * height > src_height * width) { 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Reduce the input width, but keep size/position aligned for YuvScaler 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_width = ROUNDTO2(src_height * width / height); 1790c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t iwidth_offset = ROUNDTO2((GetWidth() - src_width) / 2); 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_y += iwidth_offset; 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_u += iwidth_offset / 2; 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_v += iwidth_offset / 2; 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (src_width * height < src_height * width) { 18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Reduce the input height. 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_height = src_width * height / width; 1860c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int32_t iheight_offset = 1870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström static_cast<int32_t>((GetHeight() - src_height) >> 2); 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org iheight_offset <<= 1; // Ensure that iheight_offset is even. 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_y += iheight_offset * GetYPitch(); 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_u += iheight_offset / 2 * GetUPitch(); 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org src_v += iheight_offset / 2 * GetVPitch(); 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Scale to the output I420 frame. 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org libyuv::Scale(src_y, src_u, src_v, 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetYPitch(), GetUPitch(), GetVPitch(), 19828654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org static_cast<int>(src_width), static_cast<int>(src_height), 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst_y, dst_u, dst_v, dst_pitch_y, dst_pitch_u, dst_pitch_v, 20028654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org static_cast<int>(width), static_cast<int>(height), interpolate); 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid VideoFrame::StretchToFrame(VideoFrame* dst, 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool interpolate, bool vert_crop) const { 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!dst) { 20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "NULL dst pointer."; 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org StretchToPlanes(dst->GetYPlane(), dst->GetUPlane(), dst->GetVPlane(), 21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst->GetYPitch(), dst->GetUPitch(), dst->GetVPitch(), 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst->GetWidth(), dst->GetHeight(), 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org interpolate, vert_crop); 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dst->SetTimeStamp(GetTimeStamp()); 21517b889b899c3eeaa96dc26a6e61cd2e6296b0fecGuo-wei Shieh // Stretched frame should have the same rotation as the source. 21617b889b899c3eeaa96dc26a6e61cd2e6296b0fecGuo-wei Shieh dst->SetRotation(GetVideoRotation()); 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgVideoFrame* VideoFrame::Stretch(size_t dst_width, size_t dst_height, 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool interpolate, bool vert_crop) const { 22128654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org VideoFrame* dest = CreateEmptyFrame(static_cast<int>(dst_width), 22228654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org static_cast<int>(dst_height), 223268493a96b93d6a11a595b3272c5a4cd7a1fdc47nisse GetPixelWidth(), GetPixelHeight(), 224b09b660c53ff2c499d149e05e5c435f5057273fcmagjed GetTimeStamp()); 22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (dest) { 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org StretchToFrame(dest, interpolate, vert_crop); 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return dest; 22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool VideoFrame::SetToBlack() { 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return libyuv::I420Rect(GetYPlane(), GetYPitch(), 23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetUPlane(), GetUPitch(), 23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetVPlane(), GetVPitch(), 23528654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org 0, 0, 23628654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org static_cast<int>(GetWidth()), 23728654cbc2256230c978f41cbaf550bc2e9c2f2dbhenrike@webrtc.org static_cast<int>(GetHeight()), 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16, 128, 128) == 0; 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic const size_t kMaxSampleSize = 1000000000u; 2427e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com// Returns whether a sample is valid. 2430c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool VideoFrame::Validate(uint32_t fourcc, 2440c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int w, 2450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int h, 2460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström const uint8_t* sample, 2470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström size_t sample_size) { 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (h < 0) { 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org h = -h; 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // 16384 is maximum resolution for VP8 codec. 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (w < 1 || w > 16384 || h < 1 || h > 16384) { 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 2560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t format = CanonicalFourCC(fourcc); 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int expected_bpp = 8; 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org switch (format) { 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_I400: 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_RGGB: 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_BGGR: 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_GRBG: 26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_GBRG: 26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 8; 26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 26628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_I420: 26728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_I411: 26828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_YU12: 26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_YV12: 27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_M420: 27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_NV21: 27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_NV12: 27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 12; 27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_I422: 27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_YV16: 27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_YUY2: 27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_UYVY: 27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_RGBP: 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_RGBO: 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_R444: 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 16; 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_I444: 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_YV24: 28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_24BG: 28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_RAW: 28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 24; 28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_ABGR: 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_BGRA: 29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_ARGB: 29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 32; 29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_MJPG: 29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case FOURCC_H264: 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 0; 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org default: 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_bpp = 8; // Expect format is at least 8 bits per pixel. 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t expected_size = (w * expected_bpp + 7) / 8 * h; 30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // For compressed formats, expect 4 bits per 16 x 16 macro. I420 would be 30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // 6 bits, but grey can be 4 bits. 30828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (expected_bpp == 0) { 30928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org expected_size = ((w + 15) / 16) * ((h + 15) / 16) * 4 / 8; 31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sample == NULL) { 31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "NULL sample pointer." 31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " format: " << GetFourccName(format) 31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bpp: " << expected_bpp 31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " size: " << w << "x" << h 31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " expected: " << expected_size 31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " " << sample_size; 31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 3207e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com // TODO(fbarchard): Make function to dump information about frames. 3210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint8_t four_samples[4] = {0, 0, 0, 0}; 3225237aaf243d29732f59557361b7a993c0a18cf0etfarina for (size_t i = 0; i < arraysize(four_samples) && i < sample_size; ++i) { 3237e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com four_samples[i] = sample[i]; 3247e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com } 32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sample_size < expected_size) { 32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Size field is too small." 32728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " format: " << GetFourccName(format) 32828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bpp: " << expected_bpp 32928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " size: " << w << "x" << h 33028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " " << sample_size 33128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " expected: " << expected_size 3327e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << " sample[0..3]: " << static_cast<int>(four_samples[0]) 3337e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[1]) 3347e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[2]) 3357e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[3]); 33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (sample_size > kMaxSampleSize) { 33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Size field is invalid." 34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " format: " << GetFourccName(format) 34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bpp: " << expected_bpp 34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " size: " << w << "x" << h 34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " " << sample_size 34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " expected: " << 2 * expected_size 3457e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << " sample[0..3]: " << static_cast<int>(four_samples[0]) 3467e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[1]) 3477e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[2]) 3487e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[3]); 34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Show large size warning once every 100 frames. 3527e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com // TODO(fbarchard): Make frame counter atomic for thread safety. 35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org static int large_warn100 = 0; 35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t large_expected_size = expected_size * 2; 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (expected_bpp >= 8 && 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org (sample_size > large_expected_size || sample_size > kMaxSampleSize) && 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org large_warn100 % 100 == 0) { 35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++large_warn100; 35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Size field is too large." 36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " format: " << GetFourccName(format) 36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bpp: " << expected_bpp 36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " size: " << w << "x" << h 36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bytes: " << sample_size 36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " expected: " << large_expected_size 3657e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << " sample[0..3]: " << static_cast<int>(four_samples[0]) 3667e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[1]) 3677e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[2]) 3687e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[3]); 36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3717e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com // TODO(fbarchard): Add duplicate pixel check. 3727e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com // TODO(fbarchard): Use frame counter atomic for thread safety. 37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org static bool valid_once = true; 37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (valid_once) { 37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org valid_once = false; 37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Validate frame passed." 37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " format: " << GetFourccName(format) 37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bpp: " << expected_bpp 37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " size: " << w << "x" << h 38028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " bytes: " << sample_size 38128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " expected: " << expected_size 3827e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << " sample[0..3]: " << static_cast<int>(four_samples[0]) 3837e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[1]) 3847e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[2]) 3857e31197cb23e32dacaa7c0dd479d0cf21a23cfb8fbarchard@google.com << ", " << static_cast<int>(four_samples[3]); 38628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 38728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 38828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 38928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace cricket 391