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
Scaler()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
~Scaler()28 Scaler::~Scaler() {}
29
Set(int src_width,int src_height,int dst_width,int dst_height,VideoType src_video_type,VideoType dst_video_type,ScaleMethod method)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
Scale(const VideoFrame & src_frame,VideoFrame * dst_frame)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
SupportedVideoType(VideoType src_video_type,VideoType dst_video_type)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