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:
parent
e58112adec
commit
e2642494e4
@ -29,6 +29,7 @@ enum VideoType {
|
|||||||
kI420,
|
kI420,
|
||||||
kIYUV,
|
kIYUV,
|
||||||
kRGB24,
|
kRGB24,
|
||||||
|
kABGR,
|
||||||
kARGB,
|
kARGB,
|
||||||
kARGB4444,
|
kARGB4444,
|
||||||
kRGB565,
|
kRGB565,
|
||||||
@ -39,9 +40,9 @@ enum VideoType {
|
|||||||
kMJPG,
|
kMJPG,
|
||||||
kNV21,
|
kNV21,
|
||||||
kNV12,
|
kNV12,
|
||||||
kARGBMac,
|
kBGRA,
|
||||||
kRGBAMac,
|
kARGBMac, // TODO (mikhal): remove
|
||||||
kNumberOfVideoTypes
|
kRGBAMac, // TODO (mikhal): remove
|
||||||
};
|
};
|
||||||
|
|
||||||
// Conversion between the RawVideoType and the LibYuv videoType.
|
// Conversion between the RawVideoType and the LibYuv videoType.
|
||||||
@ -105,6 +106,32 @@ int ConvertToI420(VideoType src_video_type,
|
|||||||
bool interlaced,
|
bool interlaced,
|
||||||
VideoRotationMode rotate);
|
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
|
// 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
|
// temporarily to satisfy a linking error with the libjingle revision we and
|
||||||
// Chrome pull, due to the removed vplib.
|
// Chrome pull, due to the removed vplib.
|
||||||
@ -117,6 +144,29 @@ int ConvertFromI420(VideoType dst_video_type,
|
|||||||
uint8_t* dst_frame,
|
uint8_t* dst_frame,
|
||||||
bool interlaced,
|
bool interlaced,
|
||||||
VideoRotationMode rotate);
|
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
|
// The following list describes the designated conversion function which
|
||||||
// are called by the two prior general conversion function.
|
// are called by the two prior general conversion function.
|
||||||
|
@ -208,9 +208,10 @@ int ConvertI420ToARGB4444(const uint8_t* src_frame,
|
|||||||
int ConvertI420ToRGB565(const uint8_t* src_frame,
|
int ConvertI420ToRGB565(const uint8_t* src_frame,
|
||||||
uint8_t* dst_frame,
|
uint8_t* dst_frame,
|
||||||
int width, int height) {
|
int width, int height) {
|
||||||
|
int abs_height = (height < 0) ? -height : height;
|
||||||
const uint8_t* yplane = src_frame;
|
const uint8_t* yplane = src_frame;
|
||||||
const uint8_t* uplane = src_frame + width * height;
|
const uint8_t* uplane = src_frame + width * abs_height;
|
||||||
const uint8_t* vplane = uplane + (width * height / 4);
|
const uint8_t* vplane = uplane + (width * abs_height / 4);
|
||||||
|
|
||||||
return libyuv::I420ToRGB565(yplane, width,
|
return libyuv::I420ToRGB565(yplane, width,
|
||||||
uplane, width / 2,
|
uplane, width / 2,
|
||||||
@ -221,6 +222,7 @@ int ConvertI420ToRGB565(const uint8_t* src_frame,
|
|||||||
|
|
||||||
|
|
||||||
// Same as ConvertI420ToRGB565 with a vertical flip.
|
// Same as ConvertI420ToRGB565 with a vertical flip.
|
||||||
|
// TODO (mikhal): Deprecate
|
||||||
int ConvertI420ToRGB565Android(const uint8_t* src_frame,
|
int ConvertI420ToRGB565Android(const uint8_t* src_frame,
|
||||||
uint8_t* dst_frame,
|
uint8_t* dst_frame,
|
||||||
int width, int height) {
|
int width, int height) {
|
||||||
@ -571,12 +573,11 @@ int ConvertRGB24ToI420(int width, int height,
|
|||||||
uint8_t* yplane = dst_frame;
|
uint8_t* yplane = dst_frame;
|
||||||
uint8_t* uplane = yplane + width * height;
|
uint8_t* uplane = yplane + width * height;
|
||||||
uint8_t* vplane = uplane + (width * height / 4);
|
uint8_t* vplane = uplane + (width * height / 4);
|
||||||
// WebRtc expects a vertical flipped image.
|
|
||||||
return libyuv::RGB24ToI420(src_frame, width * 3,
|
return libyuv::RGB24ToI420(src_frame, width * 3,
|
||||||
yplane, width,
|
yplane, width,
|
||||||
uplane, width / 2,
|
uplane, width / 2,
|
||||||
vplane, width / 2,
|
vplane, width / 2,
|
||||||
width, -height);
|
width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ConvertI420ToARGBMac(const uint8_t* src_frame, uint8_t* dst_frame,
|
int ConvertI420ToARGBMac(const uint8_t* src_frame, uint8_t* dst_frame,
|
||||||
@ -612,6 +613,131 @@ int ConvertARGBMacToI420(int width, int height,
|
|||||||
width, 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,
|
int ConvertToI420(VideoType src_video_type,
|
||||||
const uint8_t* src_frame,
|
const uint8_t* src_frame,
|
||||||
int width,
|
int width,
|
||||||
@ -974,7 +1100,6 @@ double I420SSIM(const uint8_t* ref_frame,
|
|||||||
src_u_b, stride_uv,
|
src_u_b, stride_uv,
|
||||||
src_v_b, stride_uv,
|
src_v_b, stride_uv,
|
||||||
width, height);
|
width, height);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -119,27 +119,27 @@ TEST_F(TestLibYuv, ConvertTest) {
|
|||||||
// printf("\nConvert #%d I420 <-> RGB24\n", j);
|
// printf("\nConvert #%d I420 <-> RGB24\n", j);
|
||||||
uint8_t* res_rgb_buffer2 = new uint8_t[width_ * height_ * 3];
|
uint8_t* res_rgb_buffer2 = new uint8_t[width_ * height_ * 3];
|
||||||
uint8_t* res_i420_buffer = new uint8_t[frame_length_];
|
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, ConvertFromI420(orig_buffer, width_, kRGB24, 0,
|
||||||
EXPECT_EQ(0, ConvertToI420(kRGB24, res_rgb_buffer2, width_, height_,
|
width_, height_, res_rgb_buffer2));
|
||||||
res_i420_buffer, false, kRotateNone));
|
|
||||||
|
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);
|
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_);
|
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);
|
EXPECT_GT(ceil(psnr), 45);
|
||||||
j++;
|
j++;
|
||||||
delete [] res_rgb_buffer2;
|
delete [] res_rgb_buffer2;
|
||||||
|
|
||||||
// printf("\nConvert #%d I420 <-> UYVY\n", j);
|
// printf("\nConvert #%d I420 <-> UYVY\n", j);
|
||||||
uint8_t* out_uyvy_buffer = new uint8_t[width_ * height_ * 2];
|
uint8_t* out_uyvy_buffer = new uint8_t[width_ * height_ * 2];
|
||||||
EXPECT_EQ(0, ConvertFromI420(kUYVY, orig_buffer, width_,
|
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_,
|
||||||
height_, out_uyvy_buffer, false, kRotateNone));
|
kUYVY, 0, width_, height_, out_uyvy_buffer));
|
||||||
|
EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, 0, 0, width_, height_,
|
||||||
EXPECT_EQ(0, ConvertToI420(kUYVY, out_uyvy_buffer, width_, height_,
|
0, width_, height_, width_,kRotateNone, res_i420_buffer));
|
||||||
res_i420_buffer, false, kRotateNone));
|
|
||||||
//ImagePSNRfromBuffer(orig_buffer, res_i420_buffer, width_, height_, &psnr);
|
|
||||||
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
|
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
|
||||||
EXPECT_EQ(48.0, psnr);
|
EXPECT_EQ(48.0, psnr);
|
||||||
fwrite(res_i420_buffer, frame_length_, 1, output_file);
|
fwrite(res_i420_buffer, frame_length_, 1, output_file);
|
||||||
@ -149,12 +149,12 @@ TEST_F(TestLibYuv, ConvertTest) {
|
|||||||
|
|
||||||
// printf("\nConvert #%d I420 <-> I420 \n", j);
|
// printf("\nConvert #%d I420 <-> I420 \n", j);
|
||||||
uint8_t* out_i420_buffer = new uint8_t[width_ * height_ * 3 / 2 ];
|
uint8_t* out_i420_buffer = new uint8_t[width_ * height_ * 3 / 2 ];
|
||||||
EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, width_, height_,
|
EXPECT_EQ(0, ConvertToI420(kI420, orig_buffer, 0, 0, width_, height_,
|
||||||
out_i420_buffer, false, kRotateNone));
|
0, width_, height_, width_,
|
||||||
EXPECT_EQ(0, ConvertFromI420(kI420 , out_i420_buffer, width_, height_,
|
kRotateNone, out_i420_buffer));
|
||||||
res_i420_buffer, false, kRotateNone));
|
EXPECT_EQ(0, ConvertFromI420(out_i420_buffer, width_, kI420, 0,
|
||||||
|
width_, height_, res_i420_buffer));
|
||||||
fwrite(res_i420_buffer, frame_length_, 1, output_file);
|
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_);
|
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
|
||||||
EXPECT_EQ(48.0, psnr);
|
EXPECT_EQ(48.0, psnr);
|
||||||
j++;
|
j++;
|
||||||
@ -163,13 +163,14 @@ TEST_F(TestLibYuv, ConvertTest) {
|
|||||||
// printf("\nConvert #%d I420 <-> YV12\n", j);
|
// printf("\nConvert #%d I420 <-> YV12\n", j);
|
||||||
uint8_t* outYV120Buffer = new uint8_t[frame_length_];
|
uint8_t* outYV120Buffer = new uint8_t[frame_length_];
|
||||||
|
|
||||||
EXPECT_EQ(0, ConvertFromI420(kYV12, orig_buffer, width_, height_,
|
EXPECT_EQ(0, ConvertFromI420(orig_buffer, width_, kYV12, 0,
|
||||||
outYV120Buffer, false, kRotateNone));
|
width_, height_, outYV120Buffer));
|
||||||
EXPECT_EQ(0, ConvertYV12ToI420(outYV120Buffer, width_, height_,
|
EXPECT_EQ(0, ConvertFromYV12(outYV120Buffer, width_,
|
||||||
|
kI420, 0,
|
||||||
|
width_, height_,
|
||||||
res_i420_buffer));
|
res_i420_buffer));
|
||||||
fwrite(res_i420_buffer, frame_length_, 1, output_file);
|
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_);
|
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
|
||||||
EXPECT_EQ(48.0, psnr);
|
EXPECT_EQ(48.0, psnr);
|
||||||
j++;
|
j++;
|
||||||
@ -177,14 +178,14 @@ TEST_F(TestLibYuv, ConvertTest) {
|
|||||||
|
|
||||||
// printf("\nConvert #%d I420 <-> YUY2\n", j);
|
// printf("\nConvert #%d I420 <-> YUY2\n", j);
|
||||||
uint8_t* out_yuy2_buffer = new uint8_t[width_ * height_ * 2];
|
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_,
|
EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer, 0, 0, width_, height_,
|
||||||
out_yuy2_buffer, false, kRotateNone));
|
0, width_, height_, width_,
|
||||||
EXPECT_EQ(0, ConvertToI420(kYUY2, out_yuy2_buffer, width_, height_,
|
kRotateNone, res_i420_buffer));
|
||||||
res_i420_buffer, false, kRotateNone));
|
|
||||||
|
|
||||||
fwrite(res_i420_buffer, frame_length_, 1, output_file);
|
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_);
|
psnr = I420PSNR(orig_buffer, res_i420_buffer, width_, height_);
|
||||||
EXPECT_EQ(48.0, psnr);
|
EXPECT_EQ(48.0, psnr);
|
||||||
delete [] out_yuy2_buffer;
|
delete [] out_yuy2_buffer;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user