Switching Mirror functions to VideoFrame
Review URL: https://webrtc-codereview.appspot.com/834005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2834 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
0d7eaaa166
commit
2338131274
@ -130,17 +130,14 @@ int ConvertNV12ToRGB565(const uint8_t* src_frame,
|
||||
// The following 2 functions perform mirroring on a given image
|
||||
// (LeftRight/UpDown).
|
||||
// Input:
|
||||
// - width : Image width in pixels.
|
||||
// - height : Image height in pixels.
|
||||
// - src_frame : Pointer to a source frame.
|
||||
// - dst_frame : Pointer to a destination frame.
|
||||
// Return value: 0 if OK, < 0 otherwise.
|
||||
int MirrorI420LeftRight(const uint8_t* src_frame,
|
||||
uint8_t* dst_frame,
|
||||
int width, int height);
|
||||
int MirrorI420UpDown(const uint8_t* src_frame,
|
||||
uint8_t* dst_frame,
|
||||
int width, int height);
|
||||
// It is assumed that src and dst frames have equal dimensions.
|
||||
int MirrorI420LeftRight(const VideoFrame* src_frame,
|
||||
VideoFrame* dst_frame);
|
||||
int MirrorI420UpDown(const VideoFrame* src_frame,
|
||||
VideoFrame* dst_frame);
|
||||
|
||||
// Compute PSNR for an I420 frame (all planes).
|
||||
double I420PSNR(const uint8_t* ref_frame,
|
||||
|
@ -19,13 +19,13 @@
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int PrintFrame(const uint8_t* frame, int width, int height) {
|
||||
if (frame == NULL)
|
||||
int PrintBuffer(const uint8_t* buffer, int width, int height) {
|
||||
if (buffer == NULL)
|
||||
return -1;
|
||||
int k = 0;
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
printf("%d ", frame[k++]);
|
||||
printf("%d ", buffer[k++]);
|
||||
}
|
||||
printf(" \n");
|
||||
}
|
||||
@ -33,34 +33,55 @@ int PrintFrame(const uint8_t* frame, int width, int height) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PrintFrame(const uint8_t* frame, int width,
|
||||
int height, const char* str) {
|
||||
|
||||
int PrintFrame(const VideoFrame* frame, const char* str) {
|
||||
if (frame == NULL)
|
||||
return -1;
|
||||
printf("%s %dx%d \n", str, width, height);
|
||||
|
||||
const uint8_t* frame_y = frame;
|
||||
const uint8_t* frame_u = frame_y + width * height;
|
||||
const uint8_t* frame_v = frame_u + width * height / 4;
|
||||
printf("%s %dx%d \n", str, frame->Width(), frame->Height());
|
||||
|
||||
int ret = 0;
|
||||
ret += PrintFrame(frame_y, width, height);
|
||||
ret += PrintFrame(frame_u, width / 2, height / 2);
|
||||
ret += PrintFrame(frame_v, width / 2, height / 2);
|
||||
|
||||
int width = frame->Width();
|
||||
int height = frame->Height();
|
||||
ret += PrintBuffer(frame->Buffer(), width, height);
|
||||
int half_width = (frame->Width() + 1) / 2;
|
||||
int half_height = (frame->Height() + 1) / 2;
|
||||
ret += PrintBuffer(frame->Buffer() + width * height, half_width, half_height);
|
||||
ret += PrintBuffer(frame->Buffer() + width * height +
|
||||
half_width * half_height, half_width, half_height);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CreateImage(int width, int height,
|
||||
uint8_t* frame, int offset,
|
||||
int height_factor, int width_factor) {
|
||||
|
||||
// Create an image from on a YUV frame. Every plane value starts with a start
|
||||
// value, and will be set to increasing values.
|
||||
// plane_offset - prep for PlaneType.
|
||||
void CreateImage(VideoFrame* frame, int plane_offset[3]) {
|
||||
if (frame == NULL)
|
||||
return;
|
||||
int width = frame->Width();
|
||||
int height = frame->Height();
|
||||
int half_width = (frame->Width() + 1) / 2;
|
||||
int half_height = (frame->Height() + 1) / 2;
|
||||
uint8_t *data = frame->Buffer();
|
||||
// Y plane.
|
||||
for (int i = 0; i < height; i++) {
|
||||
for (int j = 0; j < width; j++) {
|
||||
*frame = static_cast<uint8_t>((i + offset) * height_factor
|
||||
+ j * width_factor);
|
||||
frame++;
|
||||
*data = static_cast<uint8_t>((i + plane_offset[0]) + j);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
// U plane.
|
||||
for (int i = 0; i < half_height; i++) {
|
||||
for (int j = 0; j < half_width; j++) {
|
||||
*data = static_cast<uint8_t>((i + plane_offset[1]) + j);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
// V Plane.
|
||||
for (int i = 0; i < half_height; i++) {
|
||||
for (int j = 0; j < half_width; j++) {
|
||||
*data = static_cast<uint8_t>((i + plane_offset[2]) + j);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -251,52 +272,63 @@ TEST_F(TestLibYuv, ConvertTest) {
|
||||
// See http://code.google.com/p/webrtc/issues/detail?id=335 for more info.
|
||||
TEST_F(TestLibYuv, DISABLED_MirrorTest) {
|
||||
// TODO (mikhal): Add an automated test to confirm output.
|
||||
// TODO(mikhal): Update to new I420VideoFrame and align values. Until then,
|
||||
// this test is disabled, only insuring build.
|
||||
std::string str;
|
||||
int width = 16;
|
||||
int height = 8;
|
||||
int factor_y = 1;
|
||||
int factor_u = 1;
|
||||
int factor_v = 1;
|
||||
int start_buffer_offset = 10;
|
||||
int length = webrtc::CalcBufferSize(kI420, width, height);
|
||||
|
||||
uint8_t* test_frame = new uint8_t[length];
|
||||
memset(test_frame, 255, length);
|
||||
VideoFrame test_frame;
|
||||
test_frame.VerifyAndAllocate(length);
|
||||
test_frame.SetWidth(width);
|
||||
test_frame.SetHeight(height);
|
||||
memset(test_frame.Buffer(), 255, length);
|
||||
|
||||
// Create input frame
|
||||
uint8_t* in_frame = test_frame;
|
||||
uint8_t* in_frame_cb = in_frame + width * height;
|
||||
uint8_t* in_frame_cr = in_frame_cb + (width * height) / 4;
|
||||
CreateImage(width, height, in_frame, 10, factor_y, 1); // Y
|
||||
CreateImage(width / 2, height / 2, in_frame_cb, 100, factor_u, 1); // Cb
|
||||
CreateImage(width / 2, height / 2, in_frame_cr, 200, factor_v, 1); // Cr
|
||||
EXPECT_EQ(0, PrintFrame(test_frame, width, height, "InputFrame"));
|
||||
// Create input frame.
|
||||
VideoFrame in_frame, test_in_frame;
|
||||
in_frame.VerifyAndAllocate(length);
|
||||
in_frame.SetWidth(width);
|
||||
in_frame.SetHeight(height);
|
||||
in_frame.SetLength(length);
|
||||
int plane_offset[3]; // prep for kNumPlanes.
|
||||
plane_offset[0] = 10;
|
||||
plane_offset[1] = 100;
|
||||
plane_offset[2] = 200;
|
||||
CreateImage(&in_frame, plane_offset);
|
||||
test_in_frame.CopyFrame(in_frame);
|
||||
EXPECT_EQ(0, PrintFrame(&in_frame, "InputFrame"));
|
||||
|
||||
uint8_t* test_frame2 = new uint8_t[length + start_buffer_offset * 2];
|
||||
memset(test_frame2, 255, length + start_buffer_offset * 2);
|
||||
uint8_t* out_frame = test_frame2;
|
||||
VideoFrame out_frame, test_out_frame;
|
||||
out_frame.VerifyAndAllocate(length);
|
||||
out_frame.SetWidth(width);
|
||||
out_frame.SetHeight(height);
|
||||
out_frame.SetLength(length);
|
||||
CreateImage(&out_frame, plane_offset);
|
||||
test_out_frame.CopyFrame(out_frame);
|
||||
|
||||
// LeftRight
|
||||
// Left-Right.
|
||||
std::cout << "Test Mirror function: LeftRight" << std::endl;
|
||||
EXPECT_EQ(0, MirrorI420LeftRight(in_frame, out_frame, width, height));
|
||||
EXPECT_EQ(0, PrintFrame(test_frame2, width, height, "OutputFrame"));
|
||||
EXPECT_EQ(0, MirrorI420LeftRight(out_frame, test_frame, width, height));
|
||||
EXPECT_EQ(0, MirrorI420LeftRight(&in_frame, &out_frame));
|
||||
EXPECT_EQ(0, PrintFrame(&out_frame, "OutputFrame"));
|
||||
EXPECT_EQ(0, MirrorI420LeftRight(&out_frame, &in_frame));
|
||||
|
||||
EXPECT_EQ(0, memcmp(in_frame, test_frame, length));
|
||||
EXPECT_EQ(0, memcmp(in_frame.Buffer(), test_in_frame.Buffer(), length));
|
||||
|
||||
// UpDown
|
||||
std::cout << "Test Mirror function: UpDown" << std::endl;
|
||||
EXPECT_EQ(0, MirrorI420UpDown(in_frame, out_frame, width, height));
|
||||
EXPECT_EQ(0, PrintFrame(test_frame2, width, height, "OutputFrame"));
|
||||
EXPECT_EQ(0, MirrorI420UpDown(out_frame, test_frame, width, height));
|
||||
|
||||
EXPECT_EQ(0, memcmp(in_frame, test_frame, length));
|
||||
EXPECT_EQ(0, MirrorI420UpDown(&in_frame, &out_frame));
|
||||
EXPECT_EQ(0, PrintFrame(&test_out_frame, "OutputFrame"));
|
||||
EXPECT_EQ(0, MirrorI420UpDown(&out_frame, &test_frame));
|
||||
EXPECT_EQ(0, memcmp(in_frame.Buffer(), test_frame.Buffer(), length));
|
||||
|
||||
// TODO(mikhal): Write to a file, and ask to look at the file.
|
||||
|
||||
std::cout << "Do the mirrored frames look correct?" << std::endl;
|
||||
delete [] test_frame;
|
||||
delete [] test_frame2;
|
||||
in_frame.Free();
|
||||
test_in_frame.Free();
|
||||
out_frame.Free();
|
||||
test_out_frame.Free();
|
||||
}
|
||||
|
||||
TEST_F(TestLibYuv, alignment) {
|
||||
|
@ -230,15 +230,20 @@ int ConvertFromYV12(const uint8_t* src_frame, int src_stride,
|
||||
ConvertVideoType(dst_video_type));
|
||||
}
|
||||
|
||||
int MirrorI420LeftRight(const uint8_t* src_frame,
|
||||
uint8_t* dst_frame,
|
||||
int width, int height) {
|
||||
int MirrorI420LeftRight(const VideoFrame* src_frame,
|
||||
VideoFrame* dst_frame) {
|
||||
// Source and destination frames should have equal resolution.
|
||||
if (src_frame->Width() != dst_frame->Width() ||
|
||||
src_frame->Height() != dst_frame->Height())
|
||||
return -1;
|
||||
int width = src_frame->Width();
|
||||
int height = src_frame->Height();
|
||||
int half_width = (width + 1) >> 1;
|
||||
int half_height = (height + 1) >> 1;
|
||||
const uint8_t* src_yplane = src_frame;
|
||||
const uint8_t* src_yplane = src_frame->Buffer();
|
||||
const uint8_t* src_uplane = src_yplane + width * height;
|
||||
const uint8_t* src_vplane = src_uplane + half_width * half_height;
|
||||
uint8_t* dst_yplane = dst_frame;
|
||||
uint8_t* dst_yplane = dst_frame->Buffer();
|
||||
uint8_t* dst_uplane = dst_yplane + width * height;
|
||||
uint8_t* dst_vplane = dst_uplane + half_width * half_height;
|
||||
return libyuv::I420Mirror(src_yplane, width,
|
||||
@ -250,15 +255,21 @@ int MirrorI420LeftRight(const uint8_t* src_frame,
|
||||
width, height);
|
||||
}
|
||||
|
||||
int MirrorI420UpDown(const uint8_t* src_frame, uint8_t* dst_frame,
|
||||
int width, int height) {
|
||||
int MirrorI420UpDown(const VideoFrame* src_frame,
|
||||
VideoFrame* dst_frame) {
|
||||
// Source and destination frames should have equal resolution
|
||||
if (src_frame->Width() != dst_frame->Width() ||
|
||||
src_frame->Height() != dst_frame->Height())
|
||||
return -1;
|
||||
int width = src_frame->Width();
|
||||
int height = src_frame->Height();
|
||||
int half_width = (width + 1) >> 1;
|
||||
int half_height = (height + 1) >> 1;
|
||||
const uint8_t* src_yplane = src_frame;
|
||||
const uint8_t* src_uplane = src_frame + width * height;
|
||||
const uint8_t* src_yplane = src_frame->Buffer();
|
||||
const uint8_t* src_uplane = src_yplane + width * height;
|
||||
const uint8_t* src_vplane = src_uplane + half_width * half_height;
|
||||
uint8_t* dst_yplane = dst_frame;
|
||||
uint8_t* dst_uplane = dst_frame + width * height;
|
||||
uint8_t* dst_yplane = dst_frame->Buffer();
|
||||
uint8_t* dst_uplane = dst_yplane + width * height;
|
||||
uint8_t* dst_vplane = dst_uplane + half_width * half_height;
|
||||
|
||||
// Inserting negative height flips the frame.
|
||||
|
@ -104,21 +104,19 @@ WebRtc_Word32 IncomingVideoStream::RenderFrame(const WebRtc_UWord32 stream_id,
|
||||
if (true == mirror_frames_enabled_) {
|
||||
transformed_video_frame_.VerifyAndAllocate(video_frame.Length());
|
||||
if (mirroring_.mirror_x_axis) {
|
||||
MirrorI420UpDown(video_frame.Buffer(),
|
||||
transformed_video_frame_.Buffer(),
|
||||
video_frame.Width(), video_frame.Height());
|
||||
transformed_video_frame_.SetLength(video_frame.Length());
|
||||
transformed_video_frame_.SetWidth(video_frame.Width());
|
||||
transformed_video_frame_.SetHeight(video_frame.Height());
|
||||
MirrorI420UpDown(&video_frame,
|
||||
&transformed_video_frame_);
|
||||
video_frame.SwapFrame(transformed_video_frame_);
|
||||
}
|
||||
if (mirroring_.mirror_y_axis) {
|
||||
MirrorI420LeftRight(video_frame.Buffer(),
|
||||
transformed_video_frame_.Buffer(),
|
||||
video_frame.Width(), video_frame.Height());
|
||||
transformed_video_frame_.SetLength(video_frame.Length());
|
||||
transformed_video_frame_.SetWidth(video_frame.Width());
|
||||
transformed_video_frame_.SetHeight(video_frame.Height());
|
||||
MirrorI420LeftRight(&video_frame,
|
||||
&transformed_video_frame_);
|
||||
video_frame.SwapFrame(transformed_video_frame_);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user