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