3
* Copyright 2011, Google Inc.
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions are met:
8
* 1. Redistributions of source code must retain the above copyright notice,
9
* this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright notice,
11
* this list of conditions and the following disclaimer in the documentation
12
* and/or other materials provided with the distribution.
13
* 3. The name of the author may not be used to endorse or promote products
14
* derived from this software without specific prior written permission.
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
#include "talk/session/phone/videoframe.h"
33
#include "libyuv/planar_functions.h"
34
#include "libyuv/scale.h"
36
#include "talk/base/logging.h"
40
// Round to 2 pixels because Chroma channels are half size.
41
#define ROUNDTO2(v) (v & ~1)
43
// TODO: Handle odd width/height with rounding.
44
void VideoFrame::StretchToPlanes(
45
uint8* y, uint8* u, uint8* v,
46
int32 dst_pitch_y, int32 dst_pitch_u, int32 dst_pitch_v,
47
size_t width, size_t height, bool interpolate, bool vert_crop) const {
49
if (!GetYPlane() || !GetUPlane() || !GetVPlane())
52
const uint8* in_y = GetYPlane();
53
const uint8* in_u = GetUPlane();
54
const uint8* in_v = GetVPlane();
55
int32 iwidth = GetWidth();
56
int32 iheight = GetHeight();
59
// Adjust the input width:height ratio to be the same as the output ratio.
60
if (iwidth * height > iheight * width) {
61
// Reduce the input width, but keep size/position aligned for YuvScaler
62
iwidth = ROUNDTO2(iheight * width / height);
63
int32 iwidth_offset = ROUNDTO2((GetWidth() - iwidth) / 2);
64
in_y += iwidth_offset;
65
in_u += iwidth_offset / 2;
66
in_v += iwidth_offset / 2;
67
} else if (iwidth * height < iheight * width) {
68
// Reduce the input height.
69
iheight = iwidth * height / width;
70
int32 iheight_offset = (GetHeight() - iheight) >> 2;
71
iheight_offset <<= 1; // Ensure that iheight_offset is even.
72
in_y += iheight_offset * GetYPitch();
73
in_u += iheight_offset / 2 * GetUPitch();
74
in_v += iheight_offset / 2 * GetVPitch();
78
// Scale to the output I420 frame.
79
libyuv::Scale(in_y, in_u, in_v,
84
y, u, v, dst_pitch_y, dst_pitch_u, dst_pitch_v,
85
width, height, interpolate);
89
size_t VideoFrame::StretchToBuffer(size_t w, size_t h,
90
uint8* buffer, size_t size,
91
bool interpolate, bool vert_crop) const {
92
if (!buffer) return 0;
94
size_t needed = SizeOf(w, h);
97
uint8* bufu = bufy + w * h;
98
uint8* bufv = bufu + ((w + 1) >> 1) * ((h + 1) >> 1);
99
StretchToPlanes(bufy, bufu, bufv, w, (w + 1) >> 1, (w + 1) >> 1, w, h,
100
interpolate, vert_crop);
105
void VideoFrame::StretchToFrame(VideoFrame *target,
106
bool interpolate, bool vert_crop) const {
109
StretchToPlanes(target->GetYPlane(),
117
interpolate, vert_crop);
118
target->SetElapsedTime(GetElapsedTime());
119
target->SetTimeStamp(GetTimeStamp());
122
VideoFrame* VideoFrame::Stretch(size_t w, size_t h,
123
bool interpolate, bool vert_crop) const {
124
VideoFrame* dest = CreateEmptyFrame(w, h, GetPixelWidth(), GetPixelHeight(),
125
GetElapsedTime(), GetTimeStamp());
127
StretchToFrame(dest, interpolate, vert_crop);
132
bool VideoFrame::SetToBlack() {
134
return libyuv::I420Rect(GetYPlane(), GetYPitch(),
135
GetUPlane(), GetUPitch(),
136
GetVPlane(), GetVPitch(),
137
0, 0, GetWidth(), GetHeight(),
140
int uv_size = GetUPitch() * GetChromaHeight();
141
memset(GetYPlane(), 16, GetWidth() * GetHeight());
142
memset(GetUPlane(), 128, uv_size);
143
memset(GetVPlane(), 128, uv_size);
148
static const size_t kMaxSampleSize = 1000000000u;
149
// Returns whether a sample is valid
150
bool VideoFrame::Validate(uint32 fourcc, int w, int h,
151
const uint8 *sample, size_t sample_size) {
155
// 16384 is maximum resolution for VP8 codec.
156
if (w < 1 || w > 16384 || h < 1 || h > 16384) {
157
LOG(LS_ERROR) << "Invalid dimensions: " << w << "x" << h;
161
// Sanity check size field is not too small or too large.
162
// 80 x 40 is less than half the minimum camera capture size
163
// even a jpeg frame will be larger than 2048 bytes.
164
if ((w * h >= 80 * 40 && sample_size < 2048) ||
165
sample_size > kMaxSampleSize) {
166
LOG(LS_ERROR) << "Invalid size field: " << sample_size;
169
if (sample == NULL) {
170
LOG(LS_ERROR) << "Invalid sample pointer";
173
// Scan pages to ensure they are there
174
// TODO: Remove or place with a faster function such as checksum.
175
for (int i = 0; i < static_cast<int>(sample_size) - 4095; i += 4096) {
176
const_cast<volatile const uint8*>(sample)[i];
178
const_cast<volatile const uint8*>(sample)[sample_size - 1];
183
} // namespace cricket