OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This webpage shows layout of YV12 and other YUV formats | 5 // This webpage shows layout of YV12 and other YUV formats |
6 // http://www.fourcc.org/yuv.php | 6 // http://www.fourcc.org/yuv.php |
7 // The actual conversion is best described here | 7 // The actual conversion is best described here |
8 // http://en.wikipedia.org/wiki/YUV | 8 // http://en.wikipedia.org/wiki/YUV |
9 // excerpt from wiki: | 9 // excerpt from wiki: |
10 // These formulae are based on the NTSC standard; | 10 // These formulae are based on the NTSC standard; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 #ifdef _OPENMP | 66 #ifdef _OPENMP |
67 #include <omp.h> | 67 #include <omp.h> |
68 #endif | 68 #endif |
69 | 69 |
70 #ifdef _DEBUG | 70 #ifdef _DEBUG |
71 #include "base/logging.h" | 71 #include "base/logging.h" |
72 #else | 72 #else |
73 #define DCHECK(a) | 73 #define DCHECK(a) |
74 #endif | 74 #endif |
75 | 75 |
| 76 // Header for low level row functions. |
76 #include "media/base/yuv_row.h" | 77 #include "media/base/yuv_row.h" |
77 | 78 |
78 namespace media { | 79 namespace media { |
79 | 80 // Convert a frame of YUV to 32 bit ARGB. |
80 // Convert a frame of YV12 (aka YUV420) to 32 bit ARGB. | 81 void ConvertYUVToRGB32(const uint8* y_buf, |
81 void ConvertYV12ToRGB32(const uint8* y_buf, | |
82 const uint8* u_buf, | 82 const uint8* u_buf, |
83 const uint8* v_buf, | 83 const uint8* v_buf, |
84 uint8* rgb_buf, | 84 uint8* rgb_buf, |
85 size_t width, | 85 int width, |
86 size_t height, | 86 int height, |
87 int y_pitch, | 87 int y_pitch, |
88 int uv_pitch, | 88 int uv_pitch, |
89 int rgb_pitch) { | 89 int rgb_pitch, |
90 // Image must be multiple of 2 in width. | 90 YUVType yuv_type) { |
91 DCHECK((width & 1) == 0); | 91 unsigned int y_shift = yuv_type; |
92 // Check alignment. Use memalign to allocate the buffer if you hit this | |
93 // check: | |
94 DCHECK((reinterpret_cast<uintptr_t>(rgb_buf) & 7) == 0); | |
95 #ifdef _OPENMP | 92 #ifdef _OPENMP |
96 #pragma omp parallel for | 93 #pragma omp parallel for |
97 #endif | 94 #endif |
98 for (int y = 0; y < static_cast<int>(height); ++y) { | 95 for (int y = 0; y < height; ++y) { |
99 uint8* d1 = rgb_buf + y * rgb_pitch; | 96 uint8* rgb_row = rgb_buf + y * rgb_pitch; |
100 const uint8* y_ptr = y_buf + y * y_pitch; | 97 const uint8* y_ptr = y_buf + y * y_pitch; |
101 const uint8* u_ptr = u_buf + y/2 * uv_pitch; | 98 const uint8* u_ptr = u_buf + (y >> y_shift) * uv_pitch; |
102 const uint8* v_ptr = v_buf + y/2 * uv_pitch; | 99 const uint8* v_ptr = v_buf + (y >> y_shift) * uv_pitch; |
103 | 100 |
104 ConvertYV12ToRGB32Row(y_ptr, | 101 FastConvertYUVToRGB32Row(y_ptr, |
105 u_ptr, | 102 u_ptr, |
106 v_ptr, | 103 v_ptr, |
107 d1, | 104 rgb_row, |
108 width); | 105 width); |
109 } | 106 } |
110 EMMS(); | 107 EMMS(); |
111 } | 108 } |
112 | 109 |
113 // Convert a frame of YV16 (aka YUV422) to 32 bit ARGB. | 110 // Scale a frame of YUV to 32 bit ARGB. |
114 void ConvertYV16ToRGB32(const uint8* y_buf, | 111 void ScaleYUVToRGB32(const uint8* y_buf, |
115 const uint8* u_buf, | 112 const uint8* u_buf, |
116 const uint8* v_buf, | 113 const uint8* v_buf, |
117 uint8* rgb_buf, | 114 uint8* rgb_buf, |
118 size_t width, | 115 int width, |
119 size_t height, | 116 int height, |
120 int y_pitch, | 117 int scaled_width, |
121 int uv_pitch, | 118 int scaled_height, |
122 int rgb_pitch) { | 119 int y_pitch, |
123 // Image must be multiple of 2 in width. | 120 int uv_pitch, |
124 DCHECK((width & 1) == 0); | 121 int rgb_pitch, |
125 // Check alignment. Use memalign to allocate the buffer if you hit this | 122 YUVType yuv_type, |
126 // check: | 123 Rotate view_rotate) { |
127 DCHECK((reinterpret_cast<uintptr_t>(rgb_buf) & 7) == 0); | 124 unsigned int y_shift = yuv_type; |
| 125 // Diagram showing origin and direction of source sampling. |
| 126 // ->0 4<- |
| 127 // 7 3 |
| 128 // |
| 129 // 6 5 |
| 130 // ->1 2<- |
| 131 // Rotations that start at right side of image. |
| 132 if ((view_rotate == ROTATE_180) || |
| 133 (view_rotate == ROTATE_270) || |
| 134 (view_rotate == MIRROR_ROTATE_0) || |
| 135 (view_rotate == MIRROR_ROTATE_90)) { |
| 136 y_buf += width - 1; |
| 137 u_buf += width / 2 - 1; |
| 138 v_buf += width / 2 - 1; |
| 139 width = -width; |
| 140 } |
| 141 // Rotations that start at bottom of image. |
| 142 if ((view_rotate == ROTATE_90) || |
| 143 (view_rotate == ROTATE_180) || |
| 144 (view_rotate == MIRROR_ROTATE_90) || |
| 145 (view_rotate == MIRROR_ROTATE_180)) { |
| 146 y_buf += (height - 1) * y_pitch; |
| 147 u_buf += ((height >> y_shift) - 1) * uv_pitch; |
| 148 v_buf += ((height >> y_shift) - 1) * uv_pitch; |
| 149 height = -height; |
| 150 } |
| 151 |
| 152 // Handle zero sized destination. |
| 153 if (scaled_width == 0 || scaled_height == 0) |
| 154 return; |
| 155 int scaled_dx = width * 16 / scaled_width; |
| 156 int scaled_dy = height * 16 / scaled_height; |
| 157 |
| 158 int scaled_dx_uv = scaled_dx; |
| 159 |
| 160 if ((view_rotate == ROTATE_90) || |
| 161 (view_rotate == ROTATE_270)) { |
| 162 int tmp = scaled_height; |
| 163 scaled_height = scaled_width; |
| 164 scaled_width = tmp; |
| 165 tmp = height; |
| 166 height = width; |
| 167 width = tmp; |
| 168 int original_dx = scaled_dx; |
| 169 int original_dy = scaled_dy; |
| 170 scaled_dx = ((original_dy >> 4) * y_pitch) << 4; |
| 171 scaled_dx_uv = ((original_dy >> 4) * uv_pitch) << 4; |
| 172 scaled_dy = original_dx; |
| 173 if (view_rotate == ROTATE_90) { |
| 174 y_pitch = -1; |
| 175 uv_pitch = -1; |
| 176 height = -height; |
| 177 } else { |
| 178 y_pitch = 1; |
| 179 uv_pitch = 1; |
| 180 } |
| 181 } |
| 182 |
128 #ifdef _OPENMP | 183 #ifdef _OPENMP |
129 #pragma omp parallel for | 184 #pragma omp parallel for |
130 #endif | 185 #endif |
131 for (int y = 0; y < static_cast<int>(height); ++y) { | 186 for (int y = 0; y < scaled_height; ++y) { |
132 uint8* d1 = rgb_buf + y * rgb_pitch; | 187 uint8* dest_pixel = rgb_buf + y * rgb_pitch; |
133 const uint8* y_ptr = y_buf + y * y_pitch; | 188 int scaled_y = (y * height / scaled_height); |
134 const uint8* u_ptr = u_buf + y * uv_pitch; | 189 const uint8* y_ptr = y_buf + scaled_y * y_pitch; |
135 const uint8* v_ptr = v_buf + y * uv_pitch; | 190 const uint8* u_ptr = u_buf + (scaled_y >> y_shift) * uv_pitch; |
| 191 const uint8* v_ptr = v_buf + (scaled_y >> y_shift) * uv_pitch; |
136 | 192 |
137 ConvertYV12ToRGB32Row(y_ptr, | 193 #if USE_MMX |
138 u_ptr, | 194 if (scaled_width == (width * 2)) { |
139 v_ptr, | 195 DoubleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
140 d1, | 196 dest_pixel, scaled_width); |
141 width); | 197 } else if ((scaled_dx & 15) == 0) { // Scaling by integer scale factor. |
| 198 if (scaled_dx_uv == scaled_dx) { // Not rotated. |
| 199 if (scaled_dx == 16) { // Not scaled |
| 200 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
| 201 dest_pixel, scaled_width); |
| 202 } else { // Simple scale down. ie half |
| 203 ConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
| 204 dest_pixel, scaled_width, scaled_dx >> 4); |
| 205 } |
| 206 } else { |
| 207 RotateConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
| 208 dest_pixel, scaled_width, |
| 209 scaled_dx >> 4, scaled_dx_uv >> 4); |
| 210 } |
| 211 #else |
| 212 if (scaled_dx == 16) { // Not scaled |
| 213 FastConvertYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
| 214 dest_pixel, scaled_width); |
| 215 #endif |
| 216 } else { |
| 217 ScaleYUVToRGB32Row(y_ptr, u_ptr, v_ptr, |
| 218 dest_pixel, scaled_width, scaled_dx); |
| 219 } |
142 } | 220 } |
143 EMMS(); | 221 EMMS(); |
144 } | 222 } |
145 | 223 |
146 } // namespace media | 224 } // namespace media |
OLD | NEW |