12cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org/* 224c65840ded84be9c945ad70e7b5a6429fa023a4leozwang@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 32cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * 42cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * Use of this source code is governed by a BSD-style license 52cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * that can be found in the LICENSE file in the root of the source 62cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * tree. An additional intellectual property rights grant can be found 72cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * in the file PATENTS. All contributing project authors may 82cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org * be found in the AUTHORS file in the root of the source tree. 92cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org */ 102cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 11c69ae69d0b25c03173fdca000c81545987ba78cepbos@webrtc.org#include "webrtc/common_video/libyuv/include/scaler.h" 122cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 13ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org#include <algorithm> 14ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org 15b2d29bd2feb49f4dd1e3ba55f95197fe8a46b9bcandrew@webrtc.org// NOTE(ajm): Path provided by gyp. 16b2d29bd2feb49f4dd1e3ba55f95197fe8a46b9bcandrew@webrtc.org#include "libyuv.h" // NOLINT 172cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 182cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.orgnamespace webrtc { 192cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 202cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.orgScaler::Scaler() 212cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org : method_(kScaleBox), 222cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org src_width_(0), 232cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org src_height_(0), 242cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org dst_width_(0), 252cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org dst_height_(0), 262cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org set_(false) {} 272cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 282cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.orgScaler::~Scaler() {} 292cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 302cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.orgint Scaler::Set(int src_width, int src_height, 312cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org int dst_width, int dst_height, 322cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org VideoType src_video_type, VideoType dst_video_type, 332cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org ScaleMethod method) { 342cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org set_ = false; 352cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org if (src_width < 1 || src_height < 1 || dst_width < 1 || dst_height < 1) 362cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return -1; 372cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 382cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org if (!SupportedVideoType(src_video_type, dst_video_type)) 392cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return -1; 402cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 412cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org src_width_ = src_width; 422cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org src_height_ = src_height; 432cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org dst_width_ = dst_width; 442cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org dst_height_ = dst_height; 452cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org method_ = method; 462cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org set_ = true; 472cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return 0; 482cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org} 492cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 504765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezint Scaler::Scale(const VideoFrame& src_frame, VideoFrame* dst_frame) { 512a476e9c95b7ec402d44fc7023f268f5b0a0bfdfmikhal@webrtc.org assert(dst_frame); 529fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org if (src_frame.IsZeroSize()) 532cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return -1; 542cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org if (!set_) 552cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return -2; 562cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 572a476e9c95b7ec402d44fc7023f268f5b0a0bfdfmikhal@webrtc.org // Making sure that destination frame is of sufficient size. 58d4e7d49628e39baf30e6aefb4536f1cf042e813bmagjed@webrtc.org dst_frame->set_video_frame_buffer( 59d4e7d49628e39baf30e6aefb4536f1cf042e813bmagjed@webrtc.org buffer_pool_.CreateBuffer(dst_width_, dst_height_)); 609fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org 61ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org // We want to preserve aspect ratio instead of stretching the frame. 62ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org // Therefore, we need to crop the source frame. Calculate the largest center 63ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org // aligned region of the source frame that can be used. 64ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const int cropped_src_width = 65ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org std::min(src_width_, dst_width_ * src_height_ / dst_height_); 66ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const int cropped_src_height = 67ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org std::min(src_height_, dst_height_ * src_width_ / dst_width_); 68ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org // Make sure the offsets are even to avoid rounding errors for the U/V planes. 69ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const int src_offset_x = ((src_width_ - cropped_src_width) / 2) & ~1; 70ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const int src_offset_y = ((src_height_ - cropped_src_height) / 2) & ~1; 71ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org 72ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const uint8_t* y_ptr = src_frame.buffer(kYPlane) + 73ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_y * src_frame.stride(kYPlane) + 74ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_x; 75ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const uint8_t* u_ptr = src_frame.buffer(kUPlane) + 76ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_y / 2 * src_frame.stride(kUPlane) + 77ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_x / 2; 78ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org const uint8_t* v_ptr = src_frame.buffer(kVPlane) + 79ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_y / 2 * src_frame.stride(kVPlane) + 80ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org src_offset_x / 2; 81ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org 82ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org return libyuv::I420Scale(y_ptr, 839fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org src_frame.stride(kYPlane), 84ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org u_ptr, 859fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org src_frame.stride(kUPlane), 86ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org v_ptr, 879fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org src_frame.stride(kVPlane), 88ea73ff726705c9af1dd3142dadc3c154a8627b55magjed@webrtc.org cropped_src_width, cropped_src_height, 899fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->buffer(kYPlane), 909fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->stride(kYPlane), 919fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->buffer(kUPlane), 929fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->stride(kUPlane), 939fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->buffer(kVPlane), 949fedff7c17a8d3dc46ed5b3207220f59a22391d6mikhal@webrtc.org dst_frame->stride(kVPlane), 952cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org dst_width_, dst_height_, 962cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org libyuv::FilterMode(method_)); 972cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org} 982cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 992cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.orgbool Scaler::SupportedVideoType(VideoType src_video_type, 1002cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org VideoType dst_video_type) { 1012cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org if (src_video_type != dst_video_type) 1022cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return false; 1032cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 1042cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org if ((src_video_type == kI420) || (src_video_type == kIYUV) || 1052cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org (src_video_type == kYV12)) 1062cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return true; 1072cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 1082cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org return false; 1092cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org} 1102cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org 1112cdb2d383303ac2a8704f09ab6673535a7a1e3bdmikhal@webrtc.org} // namespace webrtc 112