libyuv: Updating API to use latest ConvertFrom/To functionality

Review URL: http://webrtc-codereview.appspot.com/333020

git-svn-id: http://webrtc.googlecode.com/svn/trunk@1302 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
mikhal@webrtc.org 2011-12-28 21:21:40 +00:00
parent e58112adec
commit e2642494e4
3 changed files with 211 additions and 35 deletions

View File

@ -29,6 +29,7 @@ enum VideoType {
kI420,
kIYUV,
kRGB24,
kABGR,
kARGB,
kARGB4444,
kRGB565,
@ -39,9 +40,9 @@ enum VideoType {
kMJPG,
kNV21,
kNV12,
kARGBMac,
kRGBAMac,
kNumberOfVideoTypes
kBGRA,
kARGBMac, // TODO (mikhal): remove
kRGBAMac, // TODO (mikhal): remove
};
// Conversion between the RawVideoType and the LibYuv videoType.
@ -105,6 +106,32 @@ int ConvertToI420(VideoType src_video_type,
bool interlaced,
VideoRotationMode rotate);
// The previous function will soon be removed.
// TODO(mikhal): Remove legacy function after integration.
// Convert From/To I420
// Input:
// - src_video_type : Type of input video.
// - src_frame : Pointer to a source frame.
// - crop_x/crop_y : Starting positions for cropping (0 for no crop).
// - src/dst_width : src/dst width in pixels.
// - src/dst_height : src/dst height in pixels.
// - sample_size : Required only for the parsing of MJPG (set to 0 else).
// - dst_stride : Number of bytes in a row of the dst Y plane.
// - rotate : Rotation mode of output image.
// Output:
// - dst_frame : Pointer to a destination frame.
// Return value: 0 if OK, < 0 otherwise.
int ConvertToI420(VideoType src_video_type,
const uint8_t* src_frame,
int crop_x, int crop_y,
int src_width, int src_height,
int sample_size,
int dst_width, int dst_height, int dst_stride,
VideoRotationMode rotation,
uint8_t* dst_frame);
// TODO(andrew): return to the int width and height types. This was swapped
// temporarily to satisfy a linking error with the libjingle revision we and
// Chrome pull, due to the removed vplib.
@ -117,6 +144,29 @@ int ConvertFromI420(VideoType dst_video_type,
uint8_t* dst_frame,
bool interlaced,
VideoRotationMode rotate);
// The previous function will soon be removed.
// TODO(mikhal): Remove legacy function after integration.
// Input:
// - src_frame : Pointer to a source frame.
// - src_stride : Number of bytes in a row of the src Y plane.
// - dst_video_type : Type of output video.
// - dst_sample_size : Required only for the parsing of MJPG.
// - width : Width in pixels.
// - height : Height in pixels.
// - dst_frame : Pointer to a source frame.
// - dst_frame : Pointer to a destination frame.
// Return value: 0 if OK, < 0 otherwise.
int ConvertFromI420(const uint8_t* src_frame, int src_stride,
VideoType dst_video_type, int dst_sample_size,
int width, int height,
uint8_t* dst_frame);
// ConvertFrom YV12.
// Interface - same as above.
int ConvertFromYV12(const uint8_t* src_frame, int src_stride,
VideoType dst_video_type, int dst_sample_size,
int width, int height,
uint8_t* dst_frame);
// The following list describes the designated conversion function which
// are called by the two prior general conversion function.

View File

@ -208,9 +208,10 @@ int ConvertI420ToARGB4444(const uint8_t* src_frame,
int ConvertI420ToRGB565(const uint8_t* src_frame,
uint8_t* dst_frame,
int width, int height) {
int abs_height = (height < 0) ? -height : height;
const uint8_t* yplane = src_frame;
const uint8_t* uplane = src_frame + width * height;
const uint8_t* vplane = uplane + (width * height / 4);
const uint8_t* uplane = src_frame + width * abs_height;
const uint8_t* vplane = uplane + (width * abs_height / 4);
return libyuv::I420ToRGB565(yplane, width,
uplane, width / 2,
@ -221,6 +222,7 @@ int ConvertI420ToRGB565(const uint8_t* src_frame,
// Same as ConvertI420ToRGB565 with a vertical flip.
// TODO (mikhal): Deprecate
int ConvertI420ToRGB565Android(const uint8_t* src_frame,
uint8_t* dst_frame,
int width, int height) {
@ -571,12 +573,11 @@ int ConvertRGB24ToI420(int width, int height,
uint8_t* yplane = dst_frame;
uint8_t* uplane = yplane + width * height;
uint8_t* vplane = uplane + (width * height / 4);
// WebRtc expects a vertical flipped image.
return libyuv::RGB24ToI420(src_frame, width * 3,
yplane, width,
uplane, width / 2,
vplane, width / 2,
width, -height);
width, height);
}
int ConvertI420ToARGBMac(const uint8_t* src_frame, uint8_t* dst_frame,
@ -612,6 +613,131 @@ int ConvertARGBMacToI420(int width, int height,
width, height);
}
libyuv::RotationMode ConvertRotationMode(VideoRotationMode rotation) {
switch(rotation) {
case kRotateNone:
return libyuv::kRotate0;
break;
case kRotate90:
return libyuv::kRotate90;
break;
case kRotate180:
return libyuv::kRotate180;
break;
case kRotate270:
return libyuv::kRotate270;
break;
}
assert(false);
}
int ConvertVideoType(VideoType video_type) {
switch(video_type) {
case kUnknown:
return libyuv::FOURCC_ANY;
break;
case kI420:
return libyuv::FOURCC_I420;
break;
case kIYUV: // same as KYV12
case kYV12:
return libyuv::FOURCC_YV12;
break;
case kRGB24:
return libyuv::FOURCC_24BG;
break;
case kABGR:
return libyuv::FOURCC_ABGR;
break;
case kARGB4444:
case kRGB565:
case kARGB1555:
case kARGBMac:
case kRGBAMac:
// TODO(mikhal): Not supported;
assert(false);
return libyuv::FOURCC_ANY;
break;
case kYUY2:
return libyuv::FOURCC_YUY2;
break;
case kUYVY:
return libyuv::FOURCC_UYVY;
break;
case kMJPG:
return libyuv::FOURCC_MJPG;
break;
case kNV21:
return libyuv::FOURCC_NV21;
break;
case kNV12:
return libyuv::FOURCC_NV12;
break;
case kARGB:
return libyuv::FOURCC_ARGB;
break;
case kBGRA:
return libyuv::FOURCC_BGRA;
break;
}
// default value
return libyuv::FOURCC_ANY;
}
int ConvertToI420(VideoType src_video_type,
const uint8_t* src_frame,
int crop_x, int crop_y,
int src_width, int src_height,
int sample_size,
int dst_width, int dst_height, int dst_stride,
VideoRotationMode rotation,
uint8_t* dst_frame) {
// All sanity tests are conducted within LibYuv.
uint8_t* dst_yplane = dst_frame;
uint8_t* dst_uplane = dst_yplane + dst_width * dst_height;
uint8_t* dst_vplane = dst_uplane + (dst_width * dst_height / 4);
return libyuv::ConvertToI420(src_frame, sample_size,
dst_yplane, dst_stride,
dst_uplane, (dst_stride + 1) / 2,
dst_vplane, (dst_stride + 1) / 2,
crop_x, crop_y,
src_width, src_height,
dst_width, dst_height,
ConvertRotationMode(rotation),
ConvertVideoType(src_video_type));
}
int ConvertFromI420(const uint8_t* src_frame, int src_stride,
VideoType dst_video_type, int dst_sample_size,
int width, int height,
uint8_t* dst_frame) {
const uint8_t* src_yplane = src_frame;
const uint8_t* src_uplane = src_yplane + width * height;
const uint8_t* src_vplane = src_uplane + (width * height / 4);
return libyuv::ConvertFromI420(src_yplane, src_stride,
src_uplane, (src_stride + 1) / 2,
src_vplane, (src_stride + 1) / 2,
dst_frame, dst_sample_size,
width, height,
ConvertVideoType(dst_video_type));
}
int ConvertFromYV12(const uint8_t* src_frame, int src_stride,
VideoType dst_video_type, int dst_sample_size,
int width, int height,
uint8_t* dst_frame) {
const uint8_t* src_yplane = src_frame;
const uint8_t* src_uplane = src_yplane + width * height;
const uint8_t* src_vplane = src_uplane + (width * height / 4);
// YV12 = Y, V, U
return libyuv::ConvertFromI420(src_yplane, src_stride,
src_vplane, (src_stride + 1) / 2,
src_uplane, (src_stride + 1) / 2,
dst_frame, dst_sample_size,
width, height,
ConvertVideoType(dst_video_type));
}
int ConvertToI420(VideoType src_video_type,
const uint8_t* src_frame,
int width,
@ -974,7 +1100,6 @@ double I420SSIM(const uint8_t* ref_frame,
src_u_b, stride_uv,
src_v_b, stride_uv,
width, height);
}
} // namespace webrtc

View File

@ -119,27 +119,27 @@ TEST_F(TestLibYuv, ConvertTest) {
// printf("\nConvert #%d I420 <-> RGB24\n", j);
uint8_t* res_rgb_buffer2 = new uint8_t[width_ * height_ * 3];
uint8_t* res_i420_buffer = new uint8_t[frame_length_];
EXPECT_EQ(0, ConvertFromI420(kRGB24, orig_buffer, width_, height_,
res_rgb_buffer2, false, kRotateNone));
EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2, width_, height_,
res_i420_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_, kRGB24, 0,
width_, height_, res_rgb_buffer2));
EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2, 0, 0, width_, height_,
0, width_, height_, width_, kRotateNone,
res_i420_buffer));
fwrite(res_i420_buffer, frame_length_, 1, output_file);
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
// Optimization Speed- quality trade-off => 45 dB only.
// Optimization Speed- quality trade-off => 45 dB only (platform dependant).
EXPECT_GT(ceil(psnr), 45);
j++;
delete [] res_rgb_buffer2;
// printf("\nConvert #%d I420 <-> UYVY\n", j);
uint8_t* out_uyvy_buffer = new uint8_t[width_ * height_ * 2];
EXPECT_EQ(0, ConvertFromI420(kUYVY, orig_buffer, width_,
height_, out_uyvy_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, width_, height_,
res_i420_buffer, false, kRotateNone));
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_,
kUYVY, 0, width_, height_, out_uyvy_buffer));
EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, 0, 0, width_, height_,
0, width_, height_, width_,kRotateNone, res_i420_buffer));
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
EXPECT_EQ(48.0, psnr);
fwrite(res_i420_buffer, frame_length_, 1, output_file);
@ -149,12 +149,12 @@ TEST_F(TestLibYuv, ConvertTest) {
// printf("\nConvert #%d I420 <-> I420 \n", j);
uint8_t* out_i420_buffer = new uint8_t[width_ * height_ * 3 / 2 ];
EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, width_, height_,
out_i420_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertFromI420(kI420 , out_i420_buffer, width_, height_,
res_i420_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_,
0, width_, height_, width_,
kRotateNone, out_i420_buffer));
EXPECT_EQ(0, ConvertFromI420(out_i420_buffer, width_, kI420, 0,
width_, height_, res_i420_buffer));
fwrite(res_i420_buffer, frame_length_, 1, output_file);
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
EXPECT_EQ(48.0, psnr);
j++;
@ -163,13 +163,14 @@ TEST_F(TestLibYuv, ConvertTest) {
// printf("\nConvert #%d I420 <-> YV12\n", j);
uint8_t* outYV120Buffer = new uint8_t[frame_length_];
EXPECT_EQ(0, ConvertFromI420(kYV12, orig_buffer, width_, height_,
outYV120Buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertYV12ToI420(outYV120Buffer, width_, height_,
res_i420_buffer));
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_, kYV12, 0,
width_, height_, outYV120Buffer));
EXPECT_EQ(0, ConvertFromYV12(outYV120Buffer, width_,
kI420, 0,
width_, height_,
res_i420_buffer));
fwrite(res_i420_buffer, frame_length_, 1, output_file);
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
EXPECT_EQ(48.0, psnr);
j++;
@ -177,14 +178,14 @@ TEST_F(TestLibYuv, ConvertTest) {
// printf("\nConvert #%d I420 <-> YUY2\n", j);
uint8_t* out_yuy2_buffer = new uint8_t[width_ * height_ * 2];
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_,
kYUY2, 0, width_, height_, out_yuy2_buffer));
EXPECT_EQ(0, ConvertFromI420(kYUY2, orig_buffer, width_, height_,
out_yuy2_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer, width_, height_,
res_i420_buffer, false, kRotateNone));
EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer, 0, 0, width_, height_,
0, width_, height_, width_,
kRotateNone, res_i420_buffer));
fwrite(res_i420_buffer, frame_length_, 1, output_file);
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
EXPECT_EQ(48.0, psnr);
delete [] out_yuy2_buffer;