Home | History | Annotate | Download | only in libyuv
      1 /*
      2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3  *
      4  *  Use of this source code is governed by a BSD-style license
      5  *  that can be found in the LICENSE file in the root of the source
      6  *  tree. An additional intellectual property rights grant can be found
      7  *  in the file PATENTS.  All contributing project authors may
      8  *  be found in the AUTHORS file in the root of the source tree.
      9  */
     10 
     11 #include "webrtc/common_video/libyuv/include/scaler.h"
     12 
     13 #include <algorithm>
     14 
     15 // NOTE(ajm): Path provided by gyp.
     16 #include "libyuv.h"  // NOLINT
     17 
     18 namespace webrtc {
     19 
     20 Scaler::Scaler()
     21     : method_(kScaleBox),
     22       src_width_(0),
     23       src_height_(0),
     24       dst_width_(0),
     25       dst_height_(0),
     26       set_(false) {}
     27 
     28 Scaler::~Scaler() {}
     29 
     30 int Scaler::Set(int src_width, int src_height,
     31                 int dst_width, int dst_height,
     32                 VideoType src_video_type, VideoType dst_video_type,
     33                 ScaleMethod method) {
     34   set_ = false;
     35   if (src_width < 1 || src_height < 1 || dst_width < 1 || dst_height < 1)
     36     return -1;
     37 
     38   if (!SupportedVideoType(src_video_type, dst_video_type))
     39     return -1;
     40 
     41   src_width_ = src_width;
     42   src_height_ = src_height;
     43   dst_width_ = dst_width;
     44   dst_height_ = dst_height;
     45   method_ = method;
     46   set_ = true;
     47   return 0;
     48 }
     49 
     50 int Scaler::Scale(const VideoFrame& src_frame, VideoFrame* dst_frame) {
     51   assert(dst_frame);
     52   if (src_frame.IsZeroSize())
     53     return -1;
     54   if (!set_)
     55     return -2;
     56 
     57   // Making sure that destination frame is of sufficient size.
     58   dst_frame->set_video_frame_buffer(
     59       buffer_pool_.CreateBuffer(dst_width_, dst_height_));
     60 
     61   // We want to preserve aspect ratio instead of stretching the frame.
     62   // Therefore, we need to crop the source frame. Calculate the largest center
     63   // aligned region of the source frame that can be used.
     64   const int cropped_src_width =
     65       std::min(src_width_, dst_width_ * src_height_ / dst_height_);
     66   const int cropped_src_height =
     67       std::min(src_height_, dst_height_ * src_width_ / dst_width_);
     68   // Make sure the offsets are even to avoid rounding errors for the U/V planes.
     69   const int src_offset_x = ((src_width_ - cropped_src_width) / 2) & ~1;
     70   const int src_offset_y = ((src_height_ - cropped_src_height) / 2) & ~1;
     71 
     72   const uint8_t* y_ptr = src_frame.buffer(kYPlane) +
     73                          src_offset_y * src_frame.stride(kYPlane) +
     74                          src_offset_x;
     75   const uint8_t* u_ptr = src_frame.buffer(kUPlane) +
     76                          src_offset_y / 2 * src_frame.stride(kUPlane) +
     77                          src_offset_x / 2;
     78   const uint8_t* v_ptr = src_frame.buffer(kVPlane) +
     79                          src_offset_y / 2 * src_frame.stride(kVPlane) +
     80                          src_offset_x / 2;
     81 
     82   return libyuv::I420Scale(y_ptr,
     83                            src_frame.stride(kYPlane),
     84                            u_ptr,
     85                            src_frame.stride(kUPlane),
     86                            v_ptr,
     87                            src_frame.stride(kVPlane),
     88                            cropped_src_width, cropped_src_height,
     89                            dst_frame->buffer(kYPlane),
     90                            dst_frame->stride(kYPlane),
     91                            dst_frame->buffer(kUPlane),
     92                            dst_frame->stride(kUPlane),
     93                            dst_frame->buffer(kVPlane),
     94                            dst_frame->stride(kVPlane),
     95                            dst_width_, dst_height_,
     96                            libyuv::FilterMode(method_));
     97 }
     98 
     99 bool Scaler::SupportedVideoType(VideoType src_video_type,
    100                                 VideoType dst_video_type) {
    101   if (src_video_type != dst_video_type)
    102     return false;
    103 
    104   if ((src_video_type == kI420) || (src_video_type == kIYUV) ||
    105       (src_video_type == kYV12))
    106     return true;
    107 
    108   return false;
    109 }
    110 
    111 }  // namespace webrtc
    112