Delete unused video capture support for cropping, non-square pixels, and ARGB screencast scaling.

First two are unused, because the instance variables ratio_w_,
ratio_h_, and square_pixel_aspect_ratio_, are never modified after
initialization to 0 and false.

ARGB is believed to be unused, and the scaling logic
is probably not appropriate in any case.

Also delete corresponding helper functions in
videocommon.cc.
BUG=webrtc:5682

Review-Url: https://codereview.webrtc.org/1934503002
Cr-Commit-Position: refs/heads/master@{#12659}
This commit is contained in:
nisse 2016-05-09 00:47:53 -07:00 committed by Commit bot
parent 85d5108b0b
commit ba6371ec86
6 changed files with 9 additions and 571 deletions

View File

@ -30,7 +30,6 @@ static const int64_t kMaxDistance = ~(static_cast<int64_t>(1) << 63);
#ifdef WEBRTC_LINUX
static const int kYU12Penalty = 16; // Needs to be higher than MJPG index.
#endif
static const int kDefaultScreencastFps = 5;
} // namespace
@ -66,10 +65,7 @@ VideoCapturer::VideoCapturer() : apply_rotation_(false) {
}
void VideoCapturer::Construct() {
ratio_w_ = 0;
ratio_h_ = 0;
enable_camera_list_ = false;
square_pixel_aspect_ratio_ = false;
capture_state_ = CS_STOPPED;
SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured);
scaled_width_ = 0;
@ -224,152 +220,11 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
return;
}
// Use a temporary buffer to scale
std::unique_ptr<uint8_t[]> scale_buffer;
if (IsScreencast()) {
int scaled_width, scaled_height;
int desired_screencast_fps =
capture_format_.get()
? VideoFormat::IntervalToFps(capture_format_->interval)
: kDefaultScreencastFps;
ComputeScale(captured_frame->width, captured_frame->height,
desired_screencast_fps, &scaled_width, &scaled_height);
if (FOURCC_ARGB == captured_frame->fourcc &&
(scaled_width != captured_frame->width ||
scaled_height != captured_frame->height)) {
if (scaled_width != scaled_width_ || scaled_height != scaled_height_) {
LOG(LS_INFO) << "Scaling Screencast from " << captured_frame->width
<< "x" << captured_frame->height << " to " << scaled_width
<< "x" << scaled_height;
scaled_width_ = scaled_width;
scaled_height_ = scaled_height;
}
CapturedFrame* modified_frame =
const_cast<CapturedFrame*>(captured_frame);
const int modified_frame_size = scaled_width * scaled_height * 4;
scale_buffer.reset(new uint8_t[modified_frame_size]);
// Compute new width such that width * height is less than maximum but
// maintains original captured frame aspect ratio.
// Round down width to multiple of 4 so odd width won't round up beyond
// maximum, and so chroma channel is even width to simplify spatial
// resampling.
libyuv::ARGBScale(reinterpret_cast<const uint8_t*>(captured_frame->data),
captured_frame->width * 4, captured_frame->width,
captured_frame->height, scale_buffer.get(),
scaled_width * 4, scaled_width, scaled_height,
libyuv::kFilterBilinear);
modified_frame->width = scaled_width;
modified_frame->height = scaled_height;
modified_frame->data_size = scaled_width * 4 * scaled_height;
modified_frame->data = scale_buffer.get();
}
}
const int kYuy2Bpp = 2;
const int kArgbBpp = 4;
// TODO(fbarchard): Make a helper function to adjust pixels to square.
// TODO(fbarchard): Hook up experiment to scaling.
// Temporary buffer is scoped here so it will persist until i420_frame.Init()
// makes a copy of the frame, converting to I420.
std::unique_ptr<uint8_t[]> temp_buffer;
// YUY2 can be scaled vertically using an ARGB scaler. Aspect ratio is only
// a problem on OSX. OSX always converts webcams to YUY2 or UYVY.
bool can_scale =
FOURCC_YUY2 == CanonicalFourCC(captured_frame->fourcc) ||
FOURCC_UYVY == CanonicalFourCC(captured_frame->fourcc);
// If pixels are not square, optionally use vertical scaling to make them
// square. Square pixels simplify the rest of the pipeline, including
// effects and rendering.
if (can_scale && square_pixel_aspect_ratio_ &&
captured_frame->pixel_width != captured_frame->pixel_height) {
int scaled_width, scaled_height;
// modified_frame points to the captured_frame but with const casted away
// so it can be modified.
CapturedFrame* modified_frame = const_cast<CapturedFrame*>(captured_frame);
// Compute the frame size that makes pixels square pixel aspect ratio.
ComputeScaleToSquarePixels(captured_frame->width, captured_frame->height,
captured_frame->pixel_width,
captured_frame->pixel_height,
&scaled_width, &scaled_height);
if (scaled_width != scaled_width_ || scaled_height != scaled_height_) {
LOG(LS_INFO) << "Scaling WebCam from "
<< captured_frame->width << "x"
<< captured_frame->height << " to "
<< scaled_width << "x" << scaled_height
<< " for PAR "
<< captured_frame->pixel_width << "x"
<< captured_frame->pixel_height;
scaled_width_ = scaled_width;
scaled_height_ = scaled_height;
}
const int modified_frame_size = scaled_width * scaled_height * kYuy2Bpp;
uint8_t* temp_buffer_data;
// Pixels are wide and short; Increasing height. Requires temporary buffer.
if (scaled_height > captured_frame->height) {
temp_buffer.reset(new uint8_t[modified_frame_size]);
temp_buffer_data = temp_buffer.get();
} else {
// Pixels are narrow and tall; Decreasing height. Scale will be done
// in place.
temp_buffer_data = reinterpret_cast<uint8_t*>(captured_frame->data);
}
// Use ARGBScaler to vertically scale the YUY2 image, adjusting for 16 bpp.
libyuv::ARGBScale(reinterpret_cast<const uint8_t*>(captured_frame->data),
captured_frame->width * kYuy2Bpp, // Stride for YUY2.
captured_frame->width * kYuy2Bpp / kArgbBpp, // Width.
abs(captured_frame->height), // Height.
temp_buffer_data,
scaled_width * kYuy2Bpp, // Stride for YUY2.
scaled_width * kYuy2Bpp / kArgbBpp, // Width.
abs(scaled_height), // New height.
libyuv::kFilterBilinear);
modified_frame->width = scaled_width;
modified_frame->height = scaled_height;
modified_frame->pixel_width = 1;
modified_frame->pixel_height = 1;
modified_frame->data_size = modified_frame_size;
modified_frame->data = temp_buffer_data;
}
// Size to crop captured frame to. This adjusts the captured frames
// aspect ratio to match the final view aspect ratio, considering pixel
// aspect ratio and rotation. The final size may be scaled down by video
// adapter to better match ratio_w_ x ratio_h_.
// Note that abs() of frame height is passed in, because source may be
// inverted, but output will be positive.
int cropped_width = captured_frame->width;
int cropped_height = captured_frame->height;
// TODO(fbarchard): Improve logic to pad or crop.
// MJPG can crop vertically, but not horizontally. This logic disables crop.
// Alternatively we could pad the image with black, or implement a 2 step
// crop.
bool can_crop = true;
if (captured_frame->fourcc == FOURCC_MJPG) {
float cam_aspect = static_cast<float>(captured_frame->width) /
static_cast<float>(captured_frame->height);
float view_aspect = static_cast<float>(ratio_w_) /
static_cast<float>(ratio_h_);
can_crop = cam_aspect <= view_aspect;
}
if (can_crop && !IsScreencast()) {
// TODO(ronghuawu): The capturer should always produce the native
// resolution and the cropping should be done in downstream code.
ComputeCrop(ratio_w_, ratio_h_, captured_frame->width,
abs(captured_frame->height), captured_frame->pixel_width,
captured_frame->pixel_height, captured_frame->rotation,
&cropped_width, &cropped_height);
}
int adapted_width = cropped_width;
int adapted_height = cropped_height;
int adapted_width = captured_frame->width;
int adapted_height = captured_frame->height;
if (enable_video_adapter_ && !IsScreencast()) {
const VideoFormat adapted_format =
video_adapter_.AdaptFrameResolution(cropped_width, cropped_height);
video_adapter_.AdaptFrameResolution(adapted_width, adapted_height);
if (adapted_format.IsSize0x0()) {
// VideoAdapter dropped the frame.
return;
@ -383,16 +238,17 @@ void VideoCapturer::OnFrameCaptured(VideoCapturer*,
return;
}
std::unique_ptr<VideoFrame> adapted_frame(
frame_factory_->CreateAliasedFrame(captured_frame,
cropped_width, cropped_height,
adapted_width, adapted_height));
// TODO(nisse): Reorganize frame factory methods, deleting crop
// support there too.
std::unique_ptr<VideoFrame> adapted_frame(frame_factory_->CreateAliasedFrame(
captured_frame, captured_frame->width, captured_frame->height,
adapted_width, adapted_height));
if (!adapted_frame) {
// TODO(fbarchard): LOG more information about captured frame attributes.
LOG(LS_ERROR) << "Couldn't convert to I420! "
<< "From " << ToString(captured_frame) << " To "
<< cropped_width << " x " << cropped_height;
<< adapted_width << " x " << adapted_height;
return;
}

View File

@ -284,10 +284,7 @@ class VideoCapturer : public sigslot::has_slots<>,
std::unique_ptr<VideoFormat> max_format_;
std::vector<VideoFormat> filtered_supported_formats_;
int ratio_w_; // View resolution. e.g. 1280 x 720.
int ratio_h_;
bool enable_camera_list_;
bool square_pixel_aspect_ratio_; // Enable scaling to square pixels.
int scaled_width_; // Current output size from ComputeScale.
int scaled_height_;

View File

@ -323,32 +323,6 @@ TEST_F(VideoCapturerTest, SinkWantsMaxPixelAndMaxPixelCountStepUp) {
EXPECT_EQ(720, renderer2.height());
}
TEST_F(VideoCapturerTest, ScreencastScaledSuperLarge) {
InitScreencast();
const int kMaxWidth = 4096;
const int kMaxHeight = 3072;
int kWidth = kMaxWidth + 4;
int kHeight = kMaxHeight + 4;
std::vector<cricket::VideoFormat> formats;
formats.push_back(cricket::VideoFormat(kWidth, kHeight,
cricket::VideoFormat::FpsToInterval(5), cricket::FOURCC_ARGB));
capturer_->ResetSupportedFormats(formats);
EXPECT_EQ(cricket::CS_RUNNING, capturer_->Start(cricket::VideoFormat(
kWidth,
kHeight,
cricket::VideoFormat::FpsToInterval(30),
cricket::FOURCC_ARGB)));
EXPECT_TRUE(capturer_->IsRunning());
EXPECT_EQ(0, renderer_.num_rendered_frames());
EXPECT_TRUE(capturer_->CaptureFrame());
EXPECT_EQ(1, renderer_.num_rendered_frames());
EXPECT_EQ(kWidth / 2, renderer_.width());
EXPECT_EQ(kHeight / 2, renderer_.height());
}
TEST_F(VideoCapturerTest, TestFourccMatch) {
cricket::VideoFormat desired(640, 480,
cricket::VideoFormat::FpsToInterval(30),

View File

@ -51,153 +51,6 @@ uint32_t CanonicalFourCC(uint32_t fourcc) {
return fourcc;
}
static float kScaleFactors[] = {
1.f / 1.f, // Full size.
1.f / 2.f, // 1/2 scale.
1.f / 4.f, // 1/4 scale.
1.f / 8.f, // 1/8 scale.
1.f / 16.f // 1/16 scale.
};
static const int kNumScaleFactors = arraysize(kScaleFactors);
// Finds the scale factor that, when applied to width and height, produces
// fewer than num_pixels.
static float FindLowerScale(int width, int height, int target_num_pixels) {
if (!target_num_pixels) {
return 0.f;
}
int best_distance = INT_MAX;
int best_index = kNumScaleFactors - 1; // Default to max scale.
for (int i = 0; i < kNumScaleFactors; ++i) {
int test_num_pixels = static_cast<int>(width * kScaleFactors[i] *
height * kScaleFactors[i]);
int diff = target_num_pixels - test_num_pixels;
if (diff >= 0 && diff < best_distance) {
best_distance = diff;
best_index = i;
if (best_distance == 0) { // Found exact match.
break;
}
}
}
return kScaleFactors[best_index];
}
// Computes a scale less to fit in max_pixels while maintaining aspect ratio.
void ComputeScaleMaxPixels(int frame_width, int frame_height, int max_pixels,
int* scaled_width, int* scaled_height) {
ASSERT(scaled_width != NULL);
ASSERT(scaled_height != NULL);
ASSERT(max_pixels > 0);
const int kMaxWidth = 4096;
const int kMaxHeight = 3072;
int new_frame_width = frame_width;
int new_frame_height = frame_height;
// Limit width.
if (new_frame_width > kMaxWidth) {
new_frame_height = new_frame_height * kMaxWidth / new_frame_width;
new_frame_width = kMaxWidth;
}
// Limit height.
if (new_frame_height > kMaxHeight) {
new_frame_width = new_frame_width * kMaxHeight / new_frame_height;
new_frame_height = kMaxHeight;
}
// Limit number of pixels.
if (new_frame_width * new_frame_height > max_pixels) {
// Compute new width such that width * height is less than maximum but
// maintains original captured frame aspect ratio.
new_frame_width = static_cast<int>(sqrtf(static_cast<float>(
max_pixels) * new_frame_width / new_frame_height));
new_frame_height = max_pixels / new_frame_width;
}
// Snap to a scale factor that is less than or equal to target pixels.
float scale = FindLowerScale(frame_width, frame_height,
new_frame_width * new_frame_height);
*scaled_width = static_cast<int>(frame_width * scale + .5f);
*scaled_height = static_cast<int>(frame_height * scale + .5f);
}
// Compute a size to scale frames to that is below maximum compression
// and rendering size with the same aspect ratio.
void ComputeScale(int frame_width, int frame_height, int fps,
int* scaled_width, int* scaled_height) {
// Maximum pixels limit is set to Retina MacBookPro 15" resolution of
// 2880 x 1800 as of 4/18/2013.
// For high fps, maximum pixels limit is set based on common 24" monitor
// resolution of 2048 x 1280 as of 6/13/2013. The Retina resolution is
// therefore reduced to 1440 x 900.
int max_pixels = (fps > 5) ? 2048 * 1280 : 2880 * 1800;
ComputeScaleMaxPixels(
frame_width, frame_height, max_pixels, scaled_width, scaled_height);
}
// Compute size to crop video frame to.
// If cropped_format_* is 0, return the frame_* size as is.
void ComputeCrop(int cropped_format_width, int cropped_format_height,
int frame_width, int frame_height,
int pixel_width, int pixel_height,
int rotation,
int* cropped_width, int* cropped_height) {
// Transform screen crop to camera space if rotated.
if (rotation == 90 || rotation == 270) {
std::swap(cropped_format_width, cropped_format_height);
}
ASSERT(cropped_format_width >= 0);
ASSERT(cropped_format_height >= 0);
ASSERT(frame_width > 0);
ASSERT(frame_height > 0);
ASSERT(pixel_width >= 0);
ASSERT(pixel_height >= 0);
ASSERT(rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270);
ASSERT(cropped_width != NULL);
ASSERT(cropped_height != NULL);
if (!pixel_width) {
pixel_width = 1;
}
if (!pixel_height) {
pixel_height = 1;
}
// if cropped_format is 0x0 disable cropping.
if (!cropped_format_height) {
cropped_format_height = 1;
}
float frame_aspect = static_cast<float>(frame_width * pixel_width) /
static_cast<float>(frame_height * pixel_height);
float crop_aspect = static_cast<float>(cropped_format_width) /
static_cast<float>(cropped_format_height);
// kAspectThresh is the maximum aspect ratio difference that we'll accept
// for cropping. The value 1.34 allows cropping from 4:3 to 16:9.
// Set to zero to disable cropping entirely.
// TODO(fbarchard): crop to multiple of 16 width for better performance.
const float kAspectThresh = 1.34f;
// Wide aspect - crop horizontally
if (frame_aspect > crop_aspect &&
frame_aspect < crop_aspect * kAspectThresh) {
// Round width down to multiple of 4 to avoid odd chroma width.
// Width a multiple of 4 allows a half size image to have chroma channel
// that avoids rounding errors.
frame_width = static_cast<int>((crop_aspect * frame_height *
pixel_height) / pixel_width + 0.5f) & ~3;
} else if (frame_aspect < crop_aspect &&
frame_aspect > crop_aspect / kAspectThresh) {
frame_height = static_cast<int>((frame_width * pixel_width) /
(crop_aspect * pixel_height) + 0.5f) & ~1;
}
*cropped_width = frame_width;
*cropped_height = frame_height;
}
// Compute the frame size that makes pixels square pixel aspect ratio.
void ComputeScaleToSquarePixels(int in_width, int in_height,
int pixel_width, int pixel_height,
int* scaled_width, int* scaled_height) {
*scaled_width = in_width; // Keep width the same.
*scaled_height = in_height * pixel_height / pixel_width;
}
// The C++ standard requires a namespace-scope definition of static const
// integral types even when they are initialized in the declaration (see
// [class.static.data]/4), but MSVC with /Ze is non-conforming and treats that

View File

@ -135,31 +135,6 @@ inline std::string GetFourccName(uint32_t fourcc) {
return name;
}
// Computes a scale less to fit in max_pixels while maintaining aspect ratio.
void ComputeScaleMaxPixels(int frame_width, int frame_height, int max_pixels,
int* scaled_width, int* scaled_height);
// For low fps, max pixels limit is set to Retina MacBookPro 15" resolution of
// 2880 x 1800 as of 4/18/2013.
// For high fps, maximum pixels limit is set based on common 24" monitor
// resolution of 2048 x 1280 as of 6/13/2013. The Retina resolution is
// therefore reduced to 1440 x 900.
void ComputeScale(int frame_width, int frame_height, int fps,
int* scaled_width, int* scaled_height);
// Compute the frame size that conversion should crop to based on aspect ratio.
// Ensures size is multiple of 2 due to I420 and conversion limitations.
void ComputeCrop(int cropped_format_width, int cropped_format_height,
int frame_width, int frame_height,
int pixel_width, int pixel_height,
int rotation,
int* cropped_width, int* cropped_height);
// Compute the frame size that makes pixels square pixel aspect ratio.
void ComputeScaleToSquarePixels(int in_width, int in_height,
int pixel_width, int pixel_height,
int* scaled_width, int* scaled_height);
//////////////////////////////////////////////////////////////////////////////
// Definition of VideoFormat.
//////////////////////////////////////////////////////////////////////////////

View File

@ -91,221 +91,4 @@ TEST(VideoCommonTest, TestVideoFormatCompare) {
EXPECT_TRUE(format.IsPixelRateLess(format2));
}
TEST(VideoCommonTest, TestComputeScaleWithLowFps) {
int scaled_width, scaled_height;
// Request small enough. Expect no change.
ComputeScale(2560, 1600, 5, &scaled_width, &scaled_height);
EXPECT_EQ(2560, scaled_width);
EXPECT_EQ(1600, scaled_height);
// Request too many pixels. Expect 1/2 size.
ComputeScale(4096, 2560, 5, &scaled_width, &scaled_height);
EXPECT_EQ(2048, scaled_width);
EXPECT_EQ(1280, scaled_height);
// Request too many pixels and too wide and tall. Expect 1/4 size.
ComputeScale(16000, 10000, 5, &scaled_width, &scaled_height);
EXPECT_EQ(2000, scaled_width);
EXPECT_EQ(1250, scaled_height);
// Request too wide. (two 30 inch monitors). Expect 1/2 size.
ComputeScale(5120, 1600, 5, &scaled_width, &scaled_height);
EXPECT_EQ(2560, scaled_width);
EXPECT_EQ(800, scaled_height);
// Request too wide but not too many pixels. Expect 1/2 size.
ComputeScale(8192, 1024, 5, &scaled_width, &scaled_height);
EXPECT_EQ(4096, scaled_width);
EXPECT_EQ(512, scaled_height);
// Request too tall. Expect 1/4 size.
ComputeScale(1024, 8192, 5, &scaled_width, &scaled_height);
EXPECT_EQ(256, scaled_width);
EXPECT_EQ(2048, scaled_height);
}
// Same as TestComputeScale but with 15 fps instead of 5 fps.
// Disabled for UBSan: https://bugs.chromium.org/p/webrtc/issues/detail?id=5487
#ifdef UNDEFINED_SANITIZER
#define MAYBE_TestComputeScaleWithHighFps DISABLED_TestComputeScaleWithHighFps
#else
#define MAYBE_TestComputeScaleWithHighFps TestComputeScaleWithHighFps
#endif
TEST(VideoCommonTest, MAYBE_TestComputeScaleWithHighFps) {
int scaled_width, scaled_height;
// Request small enough but high fps. Expect 1/2 size.
ComputeScale(2560, 1600, 15, &scaled_width, &scaled_height);
EXPECT_EQ(1280, scaled_width);
EXPECT_EQ(800, scaled_height);
// Request too many pixels. Expect 1/2 size.
ComputeScale(4096, 2560, 15, &scaled_width, &scaled_height);
EXPECT_EQ(2048, scaled_width);
EXPECT_EQ(1280, scaled_height);
// Request too many pixels and too wide and tall. Expect 1/16 size.
ComputeScale(64000, 40000, 15, &scaled_width, &scaled_height);
EXPECT_EQ(4000, scaled_width);
EXPECT_EQ(2500, scaled_height);
// Request too wide. (two 30 inch monitors). Expect 1/2 size.
ComputeScale(5120, 1600, 15, &scaled_width, &scaled_height);
EXPECT_EQ(2560, scaled_width);
EXPECT_EQ(800, scaled_height);
// Request too wide but not too many pixels. Expect 1/2 size.
ComputeScale(8192, 1024, 15, &scaled_width, &scaled_height);
EXPECT_EQ(4096, scaled_width);
EXPECT_EQ(512, scaled_height);
// Request too tall. Expect 1/4 size.
ComputeScale(1024, 8192, 15, &scaled_width, &scaled_height);
EXPECT_EQ(256, scaled_width);
EXPECT_EQ(2048, scaled_height);
}
TEST(VideoCommonTest, TestComputeCrop) {
int cropped_width, cropped_height;
// Request 16:9 to 16:9. Expect no cropping.
ComputeCrop(1280, 720, // Crop size 16:9
640, 360, // Frame is 4:3
1, 1, // Normal 1:1 pixels
0,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(360, cropped_height);
// Request 4:3 to 16:9. Expect vertical.
ComputeCrop(640, 360, // Crop size 16:9
640, 480, // Frame is 4:3
1, 1, // Normal 1:1 pixels
0,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(360, cropped_height);
// Request 16:9 to 4:3. Expect horizontal crop.
ComputeCrop(640, 480, // Crop size 4:3
640, 360, // Frame is 16:9
1, 1, // Normal 1:1 pixels
0,
&cropped_width, &cropped_height);
EXPECT_EQ(480, cropped_width);
EXPECT_EQ(360, cropped_height);
// Request 16:9 but VGA has 3:8 pixel aspect ratio. Expect no crop.
// This occurs on HP4110 on OSX 10.5/10.6/10.7
ComputeCrop(640, 360, // Crop size 16:9
640, 480, // Frame is 4:3
3, 8, // Pixel aspect ratio is tall
0,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(480, cropped_height);
// Request 16:9 but QVGA has 15:11 pixel aspect ratio. Expect horizontal crop.
// This occurs on Logitech B910 on OSX 10.5/10.6/10.7 in Hangouts.
ComputeCrop(640, 360, // Crop size 16:9
320, 240, // Frame is 4:3
15, 11, // Pixel aspect ratio is wide
0,
&cropped_width, &cropped_height);
EXPECT_EQ(312, cropped_width);
EXPECT_EQ(240, cropped_height);
// Request 16:10 but QVGA has 15:11 pixel aspect ratio.
// Expect horizontal crop.
// This occurs on Logitech B910 on OSX 10.5/10.6/10.7 in gmail.
ComputeCrop(640, 400, // Crop size 16:10
320, 240, // Frame is 4:3
15, 11, // Pixel aspect ratio is wide
0,
&cropped_width, &cropped_height);
EXPECT_EQ(280, cropped_width);
EXPECT_EQ(240, cropped_height);
// Request 16:9 but VGA has 6:5 pixel aspect ratio. Expect vertical crop.
// This occurs on Logitech QuickCam Pro C9000 on OSX
ComputeCrop(640, 360, // Crop size 16:9
640, 480, // Frame is 4:3
6, 5, // Pixel aspect ratio is wide
0,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(432, cropped_height);
// Request 16:10 but HD is 16:9. Expect horizontal crop.
// This occurs in settings and local preview with HD experiment.
ComputeCrop(1280, 800, // Crop size 16:10
1280, 720, // Frame is 4:3
1, 1, // Pixel aspect ratio is wide
0,
&cropped_width, &cropped_height);
EXPECT_EQ(1152, cropped_width);
EXPECT_EQ(720, cropped_height);
// Request 16:9 but HD has 3:4 pixel aspect ratio. Expect vertical crop.
// This occurs on Logitech B910 on OSX 10.5/10.6.7 but not OSX 10.6.8 or 10.7
ComputeCrop(1280, 720, // Crop size 16:9
1280, 720, // Frame is 4:3
3, 4, // Pixel aspect ratio is wide
0,
&cropped_width, &cropped_height);
EXPECT_EQ(1280, cropped_width);
EXPECT_EQ(540, cropped_height);
// Request 16:9 to 3:4 (portrait). Expect no cropping.
ComputeCrop(640, 360, // Crop size 16:9
640, 480, // Frame is 3:4 portrait
1, 1, // Normal 1:1 pixels
90,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(480, cropped_height);
// Request 9:16 from VGA rotated (portrait). Expect crop.
ComputeCrop(360, 640, // Crop size 9:16
640, 480, // Frame is 3:4 portrait
1, 1, // Normal 1:1 pixels
90,
&cropped_width, &cropped_height);
EXPECT_EQ(640, cropped_width);
EXPECT_EQ(360, cropped_height);
// Cropped size 0x0. Expect no cropping.
// This is used when adding multiple capturers
ComputeCrop(0, 0, // Crop size 0x0
1024, 768, // Frame is 3:4 portrait
1, 1, // Normal 1:1 pixels
0,
&cropped_width, &cropped_height);
EXPECT_EQ(1024, cropped_width);
EXPECT_EQ(768, cropped_height);
}
TEST(VideoCommonTest, TestComputeScaleToSquarePixels) {
int scaled_width, scaled_height;
// Pixel aspect ratio is 4:3. Logical aspect ratio is 16:9. Expect scale
// to square pixels with physical aspect ratio of 16:9.
ComputeScaleToSquarePixels(640, 480,
4, 3, // 4 x 3 pixel aspect ratio
&scaled_width, &scaled_height);
EXPECT_EQ(640, scaled_width);
EXPECT_EQ(360, scaled_height);
// Pixel aspect ratio is 3:8. Physical aspect ratio is 4:3. Expect scale
// to square pixels with logical aspect ratio of 1:2.
// Note that 640x1280 will be scaled down by video adapter to view request
// of 640*360 and will end up using 320x640.
ComputeScaleToSquarePixels(640, 480,
3, 8, // 4 x 3 pixel aspect ratio
&scaled_width, &scaled_height);
EXPECT_EQ(640, scaled_width);
EXPECT_EQ(1280, scaled_height);
}
} // namespace cricket