diff --git a/README.chromium b/README.chromium index 656469ebd..fdc5836c3 100644 --- a/README.chromium +++ b/README.chromium @@ -1,6 +1,6 @@ Name: libyuv URL: http://code.google.com/p/libyuv/ -Version: 117 +Version: 118 License: BSD License File: LICENSE diff --git a/include/libyuv/convert.h b/include/libyuv/convert.h index c127eddbe..c61d04d5f 100644 --- a/include/libyuv/convert.h +++ b/include/libyuv/convert.h @@ -19,12 +19,20 @@ namespace libyuv { extern "C" { #endif +// RGB24 is also known as 24BG and BGR3 int I420ToRGB24(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_frame, int dst_stride_frame, int width, int height); +// RAW is also known as RGB3 +int I420ToRAW(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_frame, int dst_stride_frame, + int width, int height); + int I420ToARGB4444(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, diff --git a/include/libyuv/planar_functions.h b/include/libyuv/planar_functions.h index 62857ce87..730697e6d 100644 --- a/include/libyuv/planar_functions.h +++ b/include/libyuv/planar_functions.h @@ -63,6 +63,15 @@ int I444ToI420(const uint8* src_y, int src_stride_y, uint8* dst_v, int dst_stride_v, int width, int height); +// Convert I420 to I444. +int I420ToI444(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. int I400ToI420(const uint8* src_y, int src_stride_y, uint8* dst_y, int dst_stride_y, @@ -70,6 +79,11 @@ int I400ToI420(const uint8* src_y, int src_stride_y, uint8* dst_v, int dst_stride_v, int width, int height); +// Copy to I400. Source can be I420,422,444,400,NV12,NV21 +int I400Copy(const uint8* src_y, int src_stride_y, + uint8* dst_y, int dst_stride_y, + int width, int height); + // Convert NV12 to I420. Also used for NV21. int NV12ToI420(const uint8* src_y, int src_stride_y, const uint8* src_uv, int src_stride_uv, diff --git a/source/convert.cc b/source/convert.cc index d4e1cc319..4478a7f22 100644 --- a/source/convert.cc +++ b/source/convert.cc @@ -39,6 +39,7 @@ static __inline uint8 Clip(int32 val) { return (uint8) val; } +// TODO(fbarchard): rewrite with row functions int I420ToRGB24(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, @@ -108,7 +109,79 @@ int I420ToRGB24(const uint8* src_y, int src_stride_y, return 0; } +// same as RGB24 but r,g,b instead of b,g,r +// TODO(fbarchard): rewrite with row functions +int I420ToRAW(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_frame, int dst_stride_frame, + int width, int height) { + if (src_y == NULL || src_u == NULL || src_v == NULL || dst_frame == NULL) { + return -1; + } + + // RGB orientation - bottom up + // TODO(fbarchard): support inversion + uint8* out = dst_frame + dst_stride_frame * height - dst_stride_frame; + uint8* out2 = out - dst_stride_frame; + int h, w; + int tmp_r, tmp_g, tmp_b; + const uint8 *y1, *y2 ,*u, *v; + y1 = src_y; + y2 = y1 + src_stride_y; + u = src_u; + v = src_v; + for (h = ((height + 1) >> 1); h > 0; h--){ + // 2 rows at a time, 2 y's at a time + for (w = 0; w < ((width + 1) >> 1); w++){ + // Vertical and horizontal sub-sampling + tmp_r = (int32)((mapYc[y1[0]] + mapVcr[v[0]] + 128) >> 8); + tmp_g = (int32)((mapYc[y1[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8); + tmp_b = (int32)((mapYc[y1[0]] + mapUcb[u[0]] + 128) >> 8); + out[0] = Clip(tmp_r); + out[1] = Clip(tmp_g); + out[2] = Clip(tmp_b); + + tmp_r = (int32)((mapYc[y1[1]] + mapVcr[v[0]] + 128) >> 8); + tmp_g = (int32)((mapYc[y1[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8); + tmp_b = (int32)((mapYc[y1[1]] + mapUcb[u[0]] + 128) >> 8); + out[3] = Clip(tmp_r); + out[4] = Clip(tmp_g); + out[5] = Clip(tmp_b); + + tmp_r = (int32)((mapYc[y2[0]] + mapVcr[v[0]] + 128) >> 8); + tmp_g = (int32)((mapYc[y2[0]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8); + tmp_b = (int32)((mapYc[y2[0]] + mapUcb[u[0]] + 128) >> 8); + out2[0] = Clip(tmp_r); + out2[1] = Clip(tmp_g); + out2[2] = Clip(tmp_b); + + tmp_r = (int32)((mapYc[y2[1]] + mapVcr[v[0]] + 128) >> 8); + tmp_g = (int32)((mapYc[y2[1]] + mapUcg[u[0]] + mapVcg[v[0]] + 128) >> 8); + tmp_b = (int32)((mapYc[y2[1]] + mapUcb[u[0]] + 128) >> 8); + out2[3] = Clip(tmp_r); + out2[4] = Clip(tmp_g); + out2[5] = Clip(tmp_b); + + out += 6; + out2 += 6; + y1 += 2; + y2 += 2; + u++; + v++; + } + y1 += src_stride_y + src_stride_y - width; + y2 += src_stride_y + src_stride_y - width; + u += src_stride_u - ((width + 1) >> 1); + v += src_stride_v - ((width + 1) >> 1); + out -= dst_stride_frame * 3; + out2 -= dst_stride_frame * 3; + } // end height for + return 0; +} + // Little Endian... +// TODO(fbarchard): rewrite with row functions int I420ToARGB4444(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, @@ -175,7 +248,7 @@ int I420ToARGB4444(const uint8* src_y, int src_stride_y, return 0; } - +// TODO(fbarchard): rewrite with row functions int I420ToRGB565(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, @@ -254,7 +327,7 @@ int I420ToRGB565(const uint8* src_y, int src_stride_y, return 0; } - +// TODO(fbarchard): rewrite with row functions int I420ToARGB1555(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, diff --git a/source/convertfrom.cc b/source/convertfrom.cc index 6dab44fe5..930b7d7d0 100644 --- a/source/convertfrom.cc +++ b/source/convertfrom.cc @@ -57,7 +57,6 @@ int ConvertFromI420(const uint8* y, int y_stride, dst_sample, width * 3, width, height); break; -#ifdef HAVEI420TOBAYER case FOURCC_RAW: I420ToRAW(y, y_stride, u, u_stride, @@ -65,7 +64,6 @@ int ConvertFromI420(const uint8* y, int y_stride, dst_sample, width * 3, width, height); break; -#endif case FOURCC_ARGB: I420ToARGB(y, y_stride, u, u_stride, @@ -99,15 +97,11 @@ int ConvertFromI420(const uint8* y, int y_stride, width, height); break; #endif -#ifdef HAVEI420TOI400 case FOURCC_I400: - I420ToI400(y, y_stride, - u, u_stride, - v, v_stride, - dst_sample, width, - width, height); + I400Copy(y, y_stride, + dst_sample, width, + width, height); break; -#endif // Triplanar formats case FOURCC_I420: case FOURCC_YV12: { @@ -152,7 +146,6 @@ int ConvertFromI420(const uint8* y, int y_stride, width, height); break; } -#ifdef HAVEI420TOI444 case FOURCC_I444: case FOURCC_YV24: { uint8* dst_u; @@ -173,7 +166,7 @@ int ConvertFromI420(const uint8* y, int y_stride, width, height); break; } -#endif + // Formats not supported - MJPG, biplanar, some rgb formats. default: return -1; // unknown fourcc - return failure code. diff --git a/source/planar_functions.cc b/source/planar_functions.cc index 4dbcee007..7a1442d62 100644 --- a/source/planar_functions.cc +++ b/source/planar_functions.cc @@ -557,7 +557,6 @@ void ScaleRowDown2Int_SSE2(const uint8* src_ptr, int src_stride, void ScaleRowDown2Int_C(const uint8* src_ptr, int src_stride, uint8* dst_ptr, int dst_width); -// Half Width and Height int I444ToI420(const uint8* src_y, int src_stride_y, const uint8* src_u, int src_stride_u, const uint8* src_v, int src_stride_v, @@ -623,6 +622,53 @@ int I444ToI420(const uint8* src_y, int src_stride_y, 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); + +int I420ToI444(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 + CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); + + int halfwidth = (width + 1) >> 1; + int halfheight = (height + 1) >> 1; + + // Upsample U plane. + ScalePlaneBilinear(halfwidth, halfheight, + width, height, + src_stride_u, + dst_stride_u, + src_u, dst_u); + + // Upsample V plane. + ScalePlaneBilinear(halfwidth, halfheight, + width, height, + src_stride_v, + dst_stride_v, + src_v, dst_v); + return 0; +} + + static void CopyPlane2(const uint8* src, int src_stride_0, int src_stride_1, uint8* dst, int dst_stride_frame, int width, int height) { @@ -2089,6 +2135,20 @@ int I400ToI420(const uint8* src_y, int src_stride_y, return 0; } +// Copy to I400. Source can be I420,422,444,400,NV12,NV21 +int I400Copy(const uint8* src_y, int src_stride_y, + uint8* dst_y, int dst_stride_y, + int width, int height) { + // Negative height means invert the image. + if (height < 0) { + height = -height; + src_y = src_y + (height - 1) * src_stride_y; + src_stride_y = -src_stride_y; + } + CopyPlane(src_y, src_stride_y, dst_y, dst_stride_y, width, height); + return 0; +} + #ifdef __cplusplus } // extern "C" } // namespace libyuv diff --git a/source/scale.cc b/source/scale.cc index 2a8e10709..9cf7d6db7 100644 --- a/source/scale.cc +++ b/source/scale.cc @@ -3449,10 +3449,10 @@ static void ScalePlaneBilinearSimple(int src_width, int src_height, * Scale plane to/from any dimensions, with bilinear * interpolation. */ -static 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) { +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) { assert(dst_width > 0); assert(dst_height > 0); int dy = (src_height << 16) / dst_height;