Issue 4366: Adapted frames have wrong width and height and are cropped.

When a frame being stretched, the original rotation information is lost. This is to ensure it's carried over.

Also removed StretchToBuffer function as it's not called and dangerous.

BUG=4366
R=pthatcher@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/51869004

Cr-Commit-Position: refs/heads/master@{#9224}
This commit is contained in:
Guo-wei Shieh 2015-05-19 12:45:47 -07:00
parent 65de7d266c
commit 17b889b899
5 changed files with 132 additions and 33 deletions

View File

@ -103,6 +103,7 @@
'media/webrtc/webrtcvideocapturer_unittest.cc',
'media/base/videoframe_unittest.h',
'media/webrtc/webrtcvideoframe_unittest.cc',
'media/webrtc/webrtcvideoframefactory_unittest.cc',
# Disabled because some tests fail.
# TODO(ronghuawu): Reenable these tests.

View File

@ -190,28 +190,6 @@ void VideoFrame::StretchToPlanes(
static_cast<int>(width), static_cast<int>(height), interpolate);
}
size_t VideoFrame::StretchToBuffer(size_t dst_width, size_t dst_height,
uint8* dst_buffer, size_t size,
bool interpolate, bool vert_crop) const {
if (!dst_buffer) {
LOG(LS_ERROR) << "NULL dst_buffer pointer.";
return 0;
}
size_t needed = SizeOf(dst_width, dst_height);
if (needed <= size) {
uint8* dst_y = dst_buffer;
uint8* dst_u = dst_y + dst_width * dst_height;
uint8* dst_v = dst_u + ((dst_width + 1) >> 1) * ((dst_height + 1) >> 1);
StretchToPlanes(dst_y, dst_u, dst_v,
static_cast<int32>(dst_width),
static_cast<int32>((dst_width + 1) >> 1),
static_cast<int32>((dst_width + 1) >> 1),
dst_width, dst_height, interpolate, vert_crop);
}
return needed;
}
void VideoFrame::StretchToFrame(VideoFrame* dst,
bool interpolate, bool vert_crop) const {
if (!dst) {
@ -225,6 +203,8 @@ void VideoFrame::StretchToFrame(VideoFrame* dst,
interpolate, vert_crop);
dst->SetElapsedTime(GetElapsedTime());
dst->SetTimeStamp(GetTimeStamp());
// Stretched frame should have the same rotation as the source.
dst->SetRotation(GetVideoRotation());
}
VideoFrame* VideoFrame::Stretch(size_t dst_width, size_t dst_height,

View File

@ -188,16 +188,6 @@ class VideoFrame {
uint8 *y, uint8 *u, uint8 *v, int32 pitchY, int32 pitchU, int32 pitchV,
size_t width, size_t height, bool interpolate, bool crop) const;
// Writes the frame into the given frame buffer, stretched to the given width
// and height, provided that it is of sufficient size. Returns the frame's
// actual size, regardless of whether it was written or not (like snprintf).
// If there is insufficient space, nothing is written. The parameter
// "interpolate" controls whether to interpolate or just take the
// nearest-point. The parameter "crop" controls whether to crop this frame to
// the aspect ratio of the given dimensions before stretching.
virtual size_t StretchToBuffer(size_t w, size_t h, uint8 *buffer, size_t size,
bool interpolate, bool crop) const;
// Writes the frame into the target VideoFrame, stretched to the size of that
// frame. The parameter "interpolate" controls whether to interpolate or just
// take the nearest-point. The parameter "crop" controls whether to crop this
@ -230,6 +220,7 @@ class VideoFrame {
size_t pixel_height,
int64_t elapsed_time,
int64_t time_stamp) const = 0;
virtual void SetRotation(webrtc::VideoRotation rotation) = 0;
};
} // namespace cricket

View File

@ -131,7 +131,9 @@ class WebRtcVideoFrame : public VideoFrame {
const VideoFrame* GetCopyWithRotationApplied() const override;
protected:
void SetRotation(webrtc::VideoRotation rotation) { rotation_ = rotation; }
void SetRotation(webrtc::VideoRotation rotation) override {
rotation_ = rotation;
}
private:
virtual VideoFrame* CreateEmptyFrame(int w, int h, size_t pixel_width,

View File

@ -0,0 +1,125 @@
/*
* libjingle
* Copyright 2015 Google Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <string.h>
#include "talk/media/base/videoframe_unittest.h"
#include "talk/media/webrtc/webrtcvideoframe.h"
#include "talk/media/webrtc/webrtcvideoframefactory.h"
class WebRtcVideoFrameFactoryTest
: public VideoFrameTest<cricket::WebRtcVideoFrameFactory> {
public:
WebRtcVideoFrameFactoryTest() {}
void InitFrame(webrtc::VideoRotation frame_rotation) {
const int frame_width = 1920;
const int frame_height = 1080;
// Build the CapturedFrame.
captured_frame_.fourcc = cricket::FOURCC_I420;
captured_frame_.pixel_width = 1;
captured_frame_.pixel_height = 1;
captured_frame_.elapsed_time = 1234;
captured_frame_.time_stamp = 5678;
captured_frame_.rotation = frame_rotation;
captured_frame_.width = frame_width;
captured_frame_.height = frame_height;
captured_frame_.data_size =
(frame_width * frame_height) +
((frame_width + 1) / 2) * ((frame_height + 1) / 2) * 2;
captured_frame_buffer_.reset(new uint8[captured_frame_.data_size]);
// Initialize memory to satisfy DrMemory tests.
memset(captured_frame_buffer_.get(), 0, captured_frame_.data_size);
captured_frame_.data = captured_frame_buffer_.get();
}
void VerifyFrame(cricket::VideoFrame* dest_frame,
webrtc::VideoRotation src_rotation,
int src_width,
int src_height,
bool apply_rotation) {
if (!apply_rotation) {
EXPECT_EQ(dest_frame->GetRotation(), src_rotation);
EXPECT_EQ(dest_frame->GetWidth(), src_width);
EXPECT_EQ(dest_frame->GetHeight(), src_height);
} else {
EXPECT_EQ(dest_frame->GetRotation(), webrtc::kVideoRotation_0);
if (src_rotation == webrtc::kVideoRotation_90 ||
src_rotation == webrtc::kVideoRotation_270) {
EXPECT_EQ(dest_frame->GetWidth(), src_height);
EXPECT_EQ(dest_frame->GetHeight(), src_width);
} else {
EXPECT_EQ(dest_frame->GetWidth(), src_width);
EXPECT_EQ(dest_frame->GetHeight(), src_height);
}
}
}
void TestCreateAliasedFrame(bool apply_rotation) {
cricket::VideoFrameFactory& factory = factory_;
factory.SetApplyRotation(apply_rotation);
InitFrame(webrtc::kVideoRotation_270);
const cricket::CapturedFrame& captured_frame = get_captured_frame();
// Create the new frame from the CapturedFrame.
rtc::scoped_ptr<cricket::VideoFrame> frame;
int new_width = captured_frame.width / 2;
int new_height = captured_frame.height / 2;
frame.reset(factory.CreateAliasedFrame(&captured_frame, new_width,
new_height, new_width, new_height));
VerifyFrame(frame.get(), webrtc::kVideoRotation_270, new_width, new_height,
apply_rotation);
frame.reset(factory.CreateAliasedFrame(
&captured_frame, new_width, new_height, new_width / 2, new_height / 2));
VerifyFrame(frame.get(), webrtc::kVideoRotation_270, new_width / 2,
new_height / 2, apply_rotation);
// Reset the frame first so it's exclusive hence we could go through the
// StretchToFrame code path in CreateAliasedFrame.
frame.reset();
frame.reset(factory.CreateAliasedFrame(
&captured_frame, new_width, new_height, new_width / 2, new_height / 2));
VerifyFrame(frame.get(), webrtc::kVideoRotation_270, new_width / 2,
new_height / 2, apply_rotation);
}
const cricket::CapturedFrame& get_captured_frame() { return captured_frame_; }
private:
cricket::CapturedFrame captured_frame_;
rtc::scoped_ptr<uint8[]> captured_frame_buffer_;
cricket::WebRtcVideoFrameFactory factory_;
};
TEST_F(WebRtcVideoFrameFactoryTest, NoApplyRotation) {
TestCreateAliasedFrame(false);
}
TEST_F(WebRtcVideoFrameFactoryTest, ApplyRotation) {
TestCreateAliasedFrame(true);
}