OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/base/yuv_scale.h" | |
6 // yuv_row.h included to detect USE_MMX | |
7 #include "media/base/yuv_row.h" | |
8 | |
9 #ifdef _OPENMP | |
10 #include <omp.h> | |
11 #endif | |
12 | |
13 #ifdef _DEBUG | |
14 #include "base/logging.h" | |
15 #else | |
16 #define DCHECK(a) | |
17 #endif | |
18 | |
19 // TODO(fbarchard): Determine is HALF_TEST will be used or removed. | |
20 // Half test is a prototype function that may or may not be useful in the | |
21 // future. It is slower, but higher quality. The low level function | |
22 // Half2Row() is in yuv_row.h and yuv_row_win.cc. | |
23 // The function is small, so it has been left in, but if it turns out to | |
24 // be useless, it should be removed in the future. | |
25 // #define HALF_TEST 1 | |
26 | |
27 namespace media { | |
28 | |
29 // Scale a frame of YV12 (aka YUV420) to 32 bit ARGB. | |
30 void ScaleYV12ToRGB32(const uint8* y_buf, | |
31 const uint8* u_buf, | |
32 const uint8* v_buf, | |
33 uint8* rgb_buf, | |
34 int width, | |
35 int height, | |
36 int scaled_width, | |
37 int scaled_height, | |
38 int y_pitch, | |
39 int uv_pitch, | |
40 int rgb_pitch, | |
41 Rotate view_rotate) { | |
42 // Rotations that start at right side of image. | |
43 if ((view_rotate == ROTATE_180) || | |
44 (view_rotate == ROTATE_270) || | |
45 (view_rotate == MIRROR_ROTATE_0) || | |
46 (view_rotate == MIRROR_ROTATE_90)) { | |
47 y_buf += width - 1; | |
48 u_buf += width / 2 - 1; | |
49 v_buf += width / 2 - 1; | |
50 width = -width; | |
51 } | |
52 // Rotations that start at bottom of image. | |
53 if ((view_rotate == ROTATE_90) || | |
54 (view_rotate == ROTATE_180) || | |
55 (view_rotate == MIRROR_ROTATE_90) || | |
56 (view_rotate == MIRROR_ROTATE_180)) { | |
57 y_buf += (height - 1) * y_pitch; | |
58 u_buf += (height / 2 - 1) * uv_pitch; | |
59 v_buf += (height / 2 - 1) * uv_pitch; | |
60 height = -height; | |
61 } | |
62 // Only these rotations are implemented. | |
63 DCHECK((view_rotate == ROTATE_0) || | |
64 (view_rotate == ROTATE_180) || | |
65 (view_rotate == MIRROR_ROTATE_0) || | |
66 (view_rotate == MIRROR_ROTATE_180)); | |
67 | |
68 int scaled_dx = width * 16 / scaled_width; | |
69 #ifdef _OPENMP | |
70 #pragma omp parallel for | |
71 #endif | |
72 for (int y = 0; y < scaled_height; ++y) { | |
73 uint8* dest_pixel = rgb_buf + y * rgb_pitch; | |
74 int scaled_y = (y * height / scaled_height); | |
75 const uint8* y_ptr = y_buf + scaled_y * y_pitch; | |
76 const uint8* u_ptr = u_buf + scaled_y / 2 * uv_pitch; | |
77 const uint8* v_ptr = v_buf + scaled_y / 2 * uv_pitch; | |
78 if (scaled_width == width) { | |
79 ConvertYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
80 dest_pixel, scaled_width); | |
81 } else if (scaled_width == (width / 2)) { | |
82 #if HALF_TEST | |
83 uint8 y_half[2048]; | |
84 uint8 u_half[1024]; | |
85 uint8 v_half[1024]; | |
86 Half2Row(y_ptr, y_ptr + y_pitch, y_half, scaled_width); | |
87 Half2Row(u_ptr, u_ptr + uv_pitch, u_half, scaled_width / 2); | |
88 Half2Row(v_ptr, v_ptr + uv_pitch, v_half, scaled_width / 2); | |
89 ConvertYV12ToRGB32Row(y_half, u_half, v_half, | |
90 dest_pixel, scaled_width); | |
91 #else | |
92 HalfYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
93 dest_pixel, scaled_width); | |
94 #endif | |
95 } else { | |
96 ScaleYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
97 dest_pixel, scaled_width, scaled_dx); | |
98 } | |
99 } | |
100 EMMS(); | |
101 } | |
102 | |
103 // Scale a frame of YV16 (aka YUV422) to 32 bit ARGB. | |
104 void ScaleYV16ToRGB32(const uint8* y_buf, | |
105 const uint8* u_buf, | |
106 const uint8* v_buf, | |
107 uint8* rgb_buf, | |
108 int width, | |
109 int height, | |
110 int scaled_width, | |
111 int scaled_height, | |
112 int y_pitch, | |
113 int uv_pitch, | |
114 int rgb_pitch, | |
115 Rotate view_rotate) { | |
116 // Rotations that start at right side of image. | |
117 if ((view_rotate == ROTATE_180) || | |
118 (view_rotate == ROTATE_270) || | |
119 (view_rotate == MIRROR_ROTATE_0) || | |
120 (view_rotate == MIRROR_ROTATE_90)) { | |
121 y_buf += width - 1; | |
122 u_buf += width / 2 - 1; | |
123 v_buf += width / 2 - 1; | |
124 width = -width; | |
125 } | |
126 // Rotations that start at bottom of image. | |
127 if ((view_rotate == ROTATE_90) || | |
128 (view_rotate == ROTATE_180) || | |
129 (view_rotate == MIRROR_ROTATE_90) || | |
130 (view_rotate == MIRROR_ROTATE_180)) { | |
131 y_buf += (height - 1) * y_pitch; | |
132 u_buf += (height - 1) * uv_pitch; | |
133 v_buf += (height - 1) * uv_pitch; | |
134 height = -height; | |
135 } | |
136 // Only these rotations are implemented. | |
137 DCHECK((view_rotate == ROTATE_0) || | |
138 (view_rotate == ROTATE_180) || | |
139 (view_rotate == MIRROR_ROTATE_0) || | |
140 (view_rotate == MIRROR_ROTATE_180)); | |
141 int scaled_dx = width * 16 / scaled_width; | |
142 #ifdef _OPENMP | |
143 #pragma omp parallel for | |
144 #endif | |
145 for (int y = 0; y < scaled_height; ++y) { | |
146 uint8* dest_pixel = rgb_buf + y * rgb_pitch; | |
147 int scaled_y = (y * height / scaled_height); | |
148 const uint8* y_ptr = y_buf + scaled_y * y_pitch; | |
149 const uint8* u_ptr = u_buf + scaled_y * uv_pitch; | |
150 const uint8* v_ptr = v_buf + scaled_y * uv_pitch; | |
151 if (scaled_width == width) { | |
152 ConvertYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
153 dest_pixel, scaled_width); | |
154 } else if (scaled_width == (width / 2)) { | |
155 HalfYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
156 dest_pixel, scaled_width); | |
157 } else { | |
158 ScaleYV12ToRGB32Row(y_ptr, u_ptr, v_ptr, | |
159 dest_pixel, scaled_width, scaled_dx); | |
160 } | |
161 } | |
162 EMMS(); | |
163 } | |
164 | |
165 } // namespace media | |
166 | |
OLD | NEW |