Commit 8536b2f3 authored by fbarchard@google.com's avatar fbarchard@google.com

Add 411 for MJPG and fix neon warnings

BUG=none
TEST=none
Review URL: https://webrtc-codereview.appspot.com/399013

git-svn-id: http://libyuv.googlecode.com/svn/trunk@180 16f28f9a-4ce2-e073-06de-1de4eb20be90
parent 48f5dd39
Name: libyuv Name: libyuv
URL: http://code.google.com/p/libyuv/ URL: http://code.google.com/p/libyuv/
Version: 179 Version: 180
License: BSD License: BSD
License File: LICENSE License File: LICENSE
......
...@@ -49,6 +49,15 @@ int I444ToI420(const uint8* src_y, int src_stride_y, ...@@ -49,6 +49,15 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height); int width, int height);
// Convert I411 to I420.
int I411ToI420(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height);
// Convert I400 (grey) to I420. // Convert I400 (grey) to I420.
int I400ToI420(const uint8* src_y, int src_stride_y, int I400ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_y, int dst_stride_y, uint8* dst_y, int dst_stride_y,
......
...@@ -39,6 +39,14 @@ int I420ToI444(const uint8* src_y, int src_stride_y, ...@@ -39,6 +39,14 @@ int I420ToI444(const uint8* src_y, int src_stride_y,
uint8* dst_v, int dst_stride_v, uint8* dst_v, int dst_stride_v,
int width, int height); int width, int height);
int I420ToI411(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height);
// Copy to I400. Source can be I420,422,444,400,NV12,NV21 // Copy to I400. Source can be I420,422,444,400,NV12,NV21
int I400Copy(const uint8* src_y, int src_stride_y, int I400Copy(const uint8* src_y, int src_stride_y,
uint8* dst_y, int dst_stride_y, uint8* dst_y, int dst_stride_y,
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
#ifndef INCLUDE_LIBYUV_VERSION_H_ #ifndef INCLUDE_LIBYUV_VERSION_H_
#define INCLUDE_LIBYUV_VERSION_H_ #define INCLUDE_LIBYUV_VERSION_H_
#define LIBYUV_VERSION 179 #define LIBYUV_VERSION 180
#endif // INCLUDE_LIBYUV_VERSION_H_ #endif // INCLUDE_LIBYUV_VERSION_H_
...@@ -42,6 +42,7 @@ enum FourCC { ...@@ -42,6 +42,7 @@ enum FourCC {
FOURCC_I420 = FOURCC('I', '4', '2', '0'), FOURCC_I420 = FOURCC('I', '4', '2', '0'),
FOURCC_I422 = FOURCC('I', '4', '2', '2'), FOURCC_I422 = FOURCC('I', '4', '2', '2'),
FOURCC_I444 = FOURCC('I', '4', '4', '4'), FOURCC_I444 = FOURCC('I', '4', '4', '4'),
FOURCC_I411 = FOURCC('I', '4', '1', '1'),
FOURCC_I400 = FOURCC('I', '4', '0', '0'), FOURCC_I400 = FOURCC('I', '4', '0', '0'),
FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'), FOURCC_YV12 = FOURCC('Y', 'V', '1', '2'),
FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'), FOURCC_YV16 = FOURCC('Y', 'V', '1', '6'),
......
...@@ -258,6 +258,57 @@ int I444ToI420(const uint8* src_y, int src_stride_y, ...@@ -258,6 +258,57 @@ int I444ToI420(const uint8* src_y, int src_stride_y,
return 0; return 0;
} }
// use Bilinear for upsampling chroma
void ScalePlaneBilinear(int src_width, int src_height,
int dst_width, int dst_height,
int src_stride, int dst_stride,
const uint8* src_ptr, uint8* dst_ptr);
// 411 chroma is 1/4 width, 1x height
// 420 chroma is 1/2 width, 1/2 height
int I411ToI420(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height) {
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_y = dst_y + (height - 1) * dst_stride_y;
dst_u = dst_u + (height - 1) * dst_stride_u;
dst_v = dst_v + (height - 1) * dst_stride_v;
dst_stride_y = -dst_stride_y;
dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
int quarterwidth = (width + 3) >> 2;
// Resample U plane.
ScalePlaneBilinear(quarterwidth, height, // from 1/4 width, 1x height
halfwidth, halfheight, // to 1/2 width, 1/2 height
src_stride_u,
dst_stride_u,
src_u, dst_u);
// Resample V plane.
ScalePlaneBilinear(quarterwidth, height, // from 1/4 width, 1x height
halfwidth, halfheight, // to 1/2 width, 1/2 height
src_stride_v,
dst_stride_v,
src_v, dst_v);
return 0;
}
// I400 is greyscale typically used in MJPG // I400 is greyscale typically used in MJPG
int I400ToI420(const uint8* src_y, int src_stride_y, int I400ToI420(const uint8* src_y, int src_stride_y,
uint8* dst_y, int dst_stride_y, uint8* dst_y, int dst_stride_y,
...@@ -1607,6 +1658,23 @@ int ConvertToI420(const uint8* sample, size_t sample_size, ...@@ -1607,6 +1658,23 @@ int ConvertToI420(const uint8* sample, size_t sample_size,
dst_width, inv_dst_height); dst_width, inv_dst_height);
break; break;
} }
case FOURCC_I411: {
int quarterwidth = (src_width + 3) / 4;
const uint8* src_y = sample + src_width * crop_y + crop_x;
const uint8* src_u = sample + src_width * abs_src_height +
quarterwidth * crop_y + crop_x / 4;
const uint8* src_v = sample + src_width * abs_src_height +
quarterwidth * (abs_src_height + crop_y) + crop_x / 4;
I411ToI420(src_y, src_width,
src_u, quarterwidth,
src_v, quarterwidth,
y, y_stride,
u, u_stride,
v, v_stride,
dst_width, inv_dst_height);
break;
}
// Formats not supported // Formats not supported
case FOURCC_MJPG: case FOURCC_MJPG:
default: default:
......
...@@ -140,6 +140,51 @@ int I420ToI444(const uint8* src_y, int src_stride_y, ...@@ -140,6 +140,51 @@ int I420ToI444(const uint8* src_y, int src_stride_y,
return 0; return 0;
} }
// 420 chroma is 1/2 width, 1/2 height
// 411 chroma is 1/4 width, 1x height
int I420ToI411(const uint8* src_y, int src_stride_y,
const uint8* src_u, int src_stride_u,
const uint8* src_v, int src_stride_v,
uint8* dst_y, int dst_stride_y,
uint8* dst_u, int dst_stride_u,
uint8* dst_v, int dst_stride_v,
int width, int height) {
// Negative height means invert the image.
if (height < 0) {
height = -height;
dst_y = dst_y + (height - 1) * dst_stride_y;
dst_u = dst_u + (height - 1) * dst_stride_u;
dst_v = dst_v + (height - 1) * dst_stride_v;
dst_stride_y = -dst_stride_y;
dst_stride_u = -dst_stride_u;
dst_stride_v = -dst_stride_v;
}
// Copy Y plane
if (dst_y) {
CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height);
}
int halfwidth = (width + 1) >> 1;
int halfheight = (height + 1) >> 1;
int quarterwidth = (width + 3) >> 2;
// Resample U plane.
ScalePlaneBilinear(halfwidth, halfheight, // from 1/2 width, 1/2 height
quarterwidth, height, // to 1/4 width, 1x height
src_stride_u,
dst_stride_u,
src_u, dst_u);
// Resample V plane.
ScalePlaneBilinear(halfwidth, halfheight, // from 1/2 width, 1/2 height
quarterwidth, height, // to 1/4 width, 1x height
src_stride_v,
dst_stride_v,
src_v, dst_v);
return 0;
}
// Copy to I400. Source can be I420,422,444,400,NV12,NV21 // Copy to I400. Source can be I420,422,444,400,NV12,NV21
int I400Copy(const uint8* src_y, int src_stride_y, int I400Copy(const uint8* src_y, int src_stride_y,
uint8* dst_y, int dst_stride_y, uint8* dst_y, int dst_stride_y,
...@@ -1231,6 +1276,19 @@ int ConvertFromI420(const uint8* y, int y_stride, ...@@ -1231,6 +1276,19 @@ int ConvertFromI420(const uint8* y, int y_stride,
width, height); width, height);
break; break;
} }
case FOURCC_I411: {
int quarterwidth = (width + 3) / 4;
uint8* dst_u = dst_sample + width * height;
uint8* dst_v = dst_u + quarterwidth * height;
I420ToI411(y, y_stride,
u, u_stride,
v, v_stride,
dst_sample, width,
dst_u, quarterwidth,
dst_v, quarterwidth,
width, height);
break;
}
// Formats not supported - MJPG, biplanar, some rgb formats. // Formats not supported - MJPG, biplanar, some rgb formats.
default: default:
......
...@@ -107,7 +107,7 @@ void MirrorRow_NEON(const uint8* src, uint8* dst, int width) { ...@@ -107,7 +107,7 @@ void MirrorRow_NEON(const uint8* src, uint8* dst, int width) {
); );
} }
static const uint8 vtbl_4x4_transpose[16] __attribute__((vector_size(16))) = static const uvec8 vtbl_4x4_transpose =
{ 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 }; { 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15 };
void TransposeWx8_NEON(const uint8* src, int src_stride, void TransposeWx8_NEON(const uint8* src, int src_stride,
...@@ -346,7 +346,7 @@ void MirrorRowUV_NEON(const uint8* src, ...@@ -346,7 +346,7 @@ void MirrorRowUV_NEON(const uint8* src,
); );
} }
static const uint8 vtbl_4x4_transpose_di[16] __attribute__((vector_size(16))) = static const uvec8 vtbl_4x4_transpose_di =
{ 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 }; { 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 };
void TransposeUVWx8_NEON(const uint8* src, int src_stride, void TransposeUVWx8_NEON(const uint8* src, int src_stride,
......
...@@ -61,8 +61,10 @@ extern "C" { ...@@ -61,8 +61,10 @@ extern "C" {
#if defined(HAS_I420TOARGBROW_NEON) || \ #if defined(HAS_I420TOARGBROW_NEON) || \
defined(HAS_I420TOBGRAROW_NEON) || \ defined(HAS_I420TOBGRAROW_NEON) || \
defined(HAS_I420TOABGRROW_NEON) defined(HAS_I420TOABGRROW_NEON)
static const vec8 kUVToRB[8] = { 127, 127, 127, 127, 102, 102, 102, 102 }; static const vec8 kUVToRB = { 127, 127, 127, 127, 102, 102, 102, 102,
static const vec8 kUVToG[8] = { -25, -25, -25, -25, -52, -52, -52, -52 }; 0, 0, 0, 0, 0, 0, 0, 0 };
static const vec8 kUVToG = { -25, -25, -25, -25, -52, -52, -52, -52,
0, 0, 0, 0, 0, 0, 0, 0 };
#endif #endif
#if defined(HAS_I420TOARGBROW_NEON) #if defined(HAS_I420TOARGBROW_NEON)
...@@ -89,8 +91,8 @@ YUVTORGB ...@@ -89,8 +91,8 @@ YUVTORGB
"+r"(v_buf), // %2 "+r"(v_buf), // %2
"+r"(rgb_buf), // %3 "+r"(rgb_buf), // %3
"+r"(width) // %4 "+r"(width) // %4
: "r"(kUVToRB), : "r"(kUVToRB), // %5
"r"(kUVToG) "r"(kUVToG) // %6
: "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9", : "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9",
"q10", "q11", "q12", "q13", "q14", "q15" "q10", "q11", "q12", "q13", "q14", "q15"
); );
...@@ -122,8 +124,8 @@ YUVTORGB ...@@ -122,8 +124,8 @@ YUVTORGB
"+r"(v_buf), // %2 "+r"(v_buf), // %2
"+r"(rgb_buf), // %3 "+r"(rgb_buf), // %3
"+r"(width) // %4 "+r"(width) // %4
: "r"(kUVToRB), : "r"(kUVToRB), // %5
"r"(kUVToG) "r"(kUVToG) // %6
: "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9", : "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9",
"q10", "q11", "q12", "q13", "q14", "q15" "q10", "q11", "q12", "q13", "q14", "q15"
); );
...@@ -155,8 +157,8 @@ YUVTORGB ...@@ -155,8 +157,8 @@ YUVTORGB
"+r"(v_buf), // %2 "+r"(v_buf), // %2
"+r"(rgb_buf), // %3 "+r"(rgb_buf), // %3
"+r"(width) // %4 "+r"(width) // %4
: "r"(kUVToRB), : "r"(kUVToRB), // %5
"r"(kUVToG) "r"(kUVToG) // %6
: "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9", : "cc", "memory", "q0", "q1", "q2", "q3", "q8", "q9",
"q10", "q11", "q12", "q13", "q14", "q15" "q10", "q11", "q12", "q13", "q14", "q15"
); );
...@@ -174,10 +176,10 @@ void SplitUV_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) { ...@@ -174,10 +176,10 @@ void SplitUV_NEON(const uint8* src_uv, uint8* dst_u, uint8* dst_v, int pix) {
"vst1.u8 {q0}, [%1]! \n" // store U "vst1.u8 {q0}, [%1]! \n" // store U
"vst1.u8 {q1}, [%2]! \n" // Store V "vst1.u8 {q1}, [%2]! \n" // Store V
"bhi 1b \n" "bhi 1b \n"
: "+r"(src_uv), : "+r"(src_uv), // %0
"+r"(dst_u), "+r"(dst_u), // %1
"+r"(dst_v), "+r"(dst_v), // %2
"+r"(pix) // Output registers "+r"(pix) // %3 // Output registers
: // Input registers : // Input registers
: "memory", "cc", "q0", "q1" // Clobber List : "memory", "cc", "q0", "q1" // Clobber List
); );
...@@ -195,9 +197,9 @@ void CopyRow_NEON(const uint8* src, uint8* dst, int count) { ...@@ -195,9 +197,9 @@ void CopyRow_NEON(const uint8* src, uint8* dst, int count) {
"subs %2, %2, #64 \n" // 64 processed per loop "subs %2, %2, #64 \n" // 64 processed per loop
"vst1.u8 {q0,q1,q2,q3}, [%1]! \n" // store 64 "vst1.u8 {q0,q1,q2,q3}, [%1]! \n" // store 64
"bhi 1b \n" "bhi 1b \n"
: "+r"(src), : "+r"(src), // %0
"+r"(dst), "+r"(dst), // %1
"+r"(count) // Output registers "+r"(count) // %2 // Output registers
: // Input registers : // Input registers
: "memory", "cc", "q0", "q1", "q2", "q3" // Clobber List : "memory", "cc", "q0", "q1", "q2", "q3" // Clobber List
); );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment