-rw-r--r-- | noncore/multimedia/opieplayer2/yuv2rgb_arm2.c | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/noncore/multimedia/opieplayer2/yuv2rgb_arm2.c b/noncore/multimedia/opieplayer2/yuv2rgb_arm2.c index cbd32e8..91cd0b1 100644 --- a/noncore/multimedia/opieplayer2/yuv2rgb_arm2.c +++ b/noncore/multimedia/opieplayer2/yuv2rgb_arm2.c | |||
@@ -1,582 +1,583 @@ | |||
1 | /* | 1 | /* |
2 | * yuv2rgb_arm2.c | 2 | * yuv2rgb_arm2.c |
3 | * Copyright (C) 2002 Frederic 'dilb' Boulay. | 3 | * Copyright (C) 2002 Frederic 'dilb' Boulay. |
4 | * All Rights Reserved. | 4 | * All Rights Reserved. |
5 | * | 5 | * |
6 | * Author: Frederic Boulay <dilb@handhelds.org> | 6 | * Author: Frederic Boulay <dilb@handhelds.org> |
7 | * | 7 | * |
8 | * you can redistribute this file and/or modify | 8 | * you can redistribute this file and/or modify |
9 | * it under the terms of the GNU General Public License (version 2) | 9 | * it under the terms of the GNU General Public License (version 2) |
10 | * as published by the Free Software Foundation. | 10 | * as published by the Free Software Foundation. |
11 | * | 11 | * |
12 | * This file is distributed in the hope that it will be useful, | 12 | * This file is distributed in the hope that it will be useful, |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
16 | * | 16 | * |
17 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
18 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | * | 20 | * |
21 | * | 21 | * |
22 | * The function defined in this file, are derived from work done in the xine | 22 | * The function defined in this file, are derived from work done in the xine |
23 | * project. | 23 | * project. |
24 | * In order to improve performance, by strongly reducing memory bandwidth | 24 | * In order to improve performance, by strongly reducing memory bandwidth |
25 | * needed, the scaling functions are merged with the yuv2rgb function. | 25 | * needed, the scaling functions are merged with the yuv2rgb function. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #ifdef __arm__ | 28 | #ifdef __arm__ |
29 | 29 | ||
30 | #include <stdio.h> | 30 | #include <stdio.h> |
31 | #include <stdlib.h> | 31 | #include <stdlib.h> |
32 | #include <string.h> | 32 | #include <string.h> |
33 | #include <inttypes.h> | 33 | #include <inttypes.h> |
34 | 34 | ||
35 | #include "yuv2rgb.h" | 35 | #include "yuv2rgb.h" |
36 | #include <xine/xineutils.h> | 36 | #include <xine/xineutils.h> |
37 | 37 | ||
38 | /* Prototypes of the "local" functions available here: */ | 38 | /* Prototypes of the "local" functions available here: */ |
39 | /* first prototype, function called when no scaling is needed: */ | 39 | /* first prototype, function called when no scaling is needed: */ |
40 | static void arm_rgb16_noscale(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 40 | static void arm_rgb16_noscale(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
41 | /* second prototype, function called when no horizontal scaling is needed: */ | 41 | /* second prototype, function called when no horizontal scaling is needed: */ |
42 | static void arm_rgb16_step_dx_32768(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 42 | static void arm_rgb16_step_dx_32768(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
43 | /* third prototype, function called when scaling is needed for zooming in: */ | 43 | /* third prototype, function called when scaling is needed for zooming in: */ |
44 | static void arm_rgb16_step_dx_inf_32768(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 44 | static void arm_rgb16_step_dx_inf_32768(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
45 | /* fourth prototype, function called when scaling is needed for zooming out (between 1x and 2x): */ | 45 | /* fourth prototype, function called when scaling is needed for zooming out (between 1x and 2x): */ |
46 | static void arm_rgb16_step_dx_bet_32768_65536(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 46 | static void arm_rgb16_step_dx_bet_32768_65536(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
47 | /* fifth prototype, function called when scaling is needed for zooming out (greater than 2x): */ | 47 | /* fifth prototype, function called when scaling is needed for zooming out (greater than 2x): */ |
48 | static void arm_rgb16_step_dx_sup_65536(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 48 | static void arm_rgb16_step_dx_sup_65536(yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
49 | /* sixth prototype, function where the decision of the scaling function to use is made.*/ | 49 | /* sixth prototype, function where the decision of the scaling function to use is made.*/ |
50 | static void arm_rgb16_2 (yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); | 50 | static void arm_rgb16_2 (yuv2rgb_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); |
51 | 51 | ||
52 | 52 | ||
53 | 53 | ||
54 | 54 | ||
55 | /* extern function: */ | 55 | /* extern function: */ |
56 | 56 | ||
57 | /* Function: */ | 57 | /* Function: */ |
58 | void yuv2rgb_init_arm (yuv2rgb_factory_t *this) | 58 | void yuv2rgb_init_arm (yuv2rgb_factory_t *this) |
59 | /* This function initialise the member yuv2rgb_fun, if everything is right | 59 | /* This function initialise the member yuv2rgb_fun, if everything is right |
60 | the function optimised for the arm target should be used.*/ | 60 | the function optimised for the arm target should be used.*/ |
61 | { | 61 | { |
62 | if (this->swapped) | 62 | if (this->swapped) |
63 | return; /*no swapped pixel output upto now*/ | 63 | return; /*no swapped pixel output upto now*/ |
64 | 64 | ||
65 | switch (this->mode) | 65 | switch (this->mode) |
66 | { | 66 | { |
67 | case MODE_16_RGB: | 67 | case MODE_16_RGB: |
68 | this->yuv2rgb_fun = arm_rgb16_2; | 68 | this->yuv2rgb_fun = arm_rgb16_2; |
69 | break; | 69 | break; |
70 | default: | 70 | default: |
71 | break; | ||
71 | } | 72 | } |
72 | } | 73 | } |
73 | 74 | ||
74 | 75 | ||
75 | 76 | ||
76 | /* local functions: */ | 77 | /* local functions: */ |
77 | 78 | ||
78 | /* Function: */ | 79 | /* Function: */ |
79 | static void arm_rgb16_2 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) | 80 | static void arm_rgb16_2 (yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) |
80 | /* This function takes care of applying the right scaling conversion | 81 | /* This function takes care of applying the right scaling conversion |
81 | (yuv2rgb is included in each scaling function!)*/ | 82 | (yuv2rgb is included in each scaling function!)*/ |
82 | { | 83 | { |
83 | if (!this->do_scale) | 84 | if (!this->do_scale) |
84 | { | 85 | { |
85 | arm_rgb16_noscale(this, _dst, _py, _pu, _pv); | 86 | arm_rgb16_noscale(this, _dst, _py, _pu, _pv); |
86 | return; | 87 | return; |
87 | } | 88 | } |
88 | if (this->step_dx<32768) | 89 | if (this->step_dx<32768) |
89 | { | 90 | { |
90 | arm_rgb16_step_dx_inf_32768(this, _dst, _py, _pu, _pv); | 91 | arm_rgb16_step_dx_inf_32768(this, _dst, _py, _pu, _pv); |
91 | return; | 92 | return; |
92 | } | 93 | } |
93 | if (this->step_dx==32768) | 94 | if (this->step_dx==32768) |
94 | { | 95 | { |
95 | arm_rgb16_step_dx_32768(this, _dst, _py, _pu, _pv); | 96 | arm_rgb16_step_dx_32768(this, _dst, _py, _pu, _pv); |
96 | return; | 97 | return; |
97 | } | 98 | } |
98 | if (this->step_dx<65536) | 99 | if (this->step_dx<65536) |
99 | { | 100 | { |
100 | arm_rgb16_step_dx_bet_32768_65536(this, _dst, _py, _pu, _pv); | 101 | arm_rgb16_step_dx_bet_32768_65536(this, _dst, _py, _pu, _pv); |
101 | return; | 102 | return; |
102 | } | 103 | } |
103 | arm_rgb16_step_dx_sup_65536(this, _dst, _py, _pu, _pv); | 104 | arm_rgb16_step_dx_sup_65536(this, _dst, _py, _pu, _pv); |
104 | return; | 105 | return; |
105 | } | 106 | } |
106 | 107 | ||
107 | 108 | ||
108 | /* Function: */ | 109 | /* Function: */ |
109 | static void arm_rgb16_noscale(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) | 110 | static void arm_rgb16_noscale(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) |
110 | /* This function is called when the source and the destination pictures have the same size. | 111 | /* This function is called when the source and the destination pictures have the same size. |
111 | In this case, scaling part is not needed. | 112 | In this case, scaling part is not needed. |
112 | (This code is probably far from being optimised, in particular, the asm | 113 | (This code is probably far from being optimised, in particular, the asm |
113 | generated is not the most efficient, a pure asm version will probably | 114 | generated is not the most efficient, a pure asm version will probably |
114 | emerge sooner or later). But at least, this version is faster than what | 115 | emerge sooner or later). But at least, this version is faster than what |
115 | was used before.*/ | 116 | was used before.*/ |
116 | { | 117 | { |
117 | int height; | 118 | int height; |
118 | 119 | ||
119 | height=this->dest_height; | 120 | height=this->dest_height; |
120 | 121 | ||
121 | while (height>0) | 122 | while (height>0) |
122 | { | 123 | { |
123 | uint16_t *r, *g, *b; | 124 | uint16_t *r, *g, *b; |
124 | uint8_t *py, *py2, *pu, *pv; | 125 | uint8_t *py, *py2, *pu, *pv; |
125 | uint16_t *dst, *dst2; | 126 | uint16_t *dst, *dst2; |
126 | int width; | 127 | int width; |
127 | register uint8_t p1y, p1u, p1v; | 128 | register uint8_t p1y, p1u, p1v; |
128 | 129 | ||
129 | height-=2; | 130 | height-=2; |
130 | width=this->dest_width; | 131 | width=this->dest_width; |
131 | dst = _dst; | 132 | dst = _dst; |
132 | dst2 = _dst + this->rgb_stride; | 133 | dst2 = _dst + this->rgb_stride; |
133 | py = _py; | 134 | py = _py; |
134 | py2 = _py + this->y_stride; | 135 | py2 = _py + this->y_stride; |
135 | pu = _pu; | 136 | pu = _pu; |
136 | pv = _pv; | 137 | pv = _pv; |
137 | 138 | ||
138 | while (width>0) | 139 | while (width>0) |
139 | { | 140 | { |
140 | width-=2; | 141 | width-=2; |
141 | p1y=*py++; | 142 | p1y=*py++; |
142 | p1u=*pu++; | 143 | p1u=*pu++; |
143 | p1v=*pv++; | 144 | p1v=*pv++; |
144 | 145 | ||
145 | r = this->table_rV[p1v]; | 146 | r = this->table_rV[p1v]; |
146 | g = (void *) (((uint8_t *)this->table_gU[p1u]) + this->table_gV[p1v]); | 147 | g = (void *) (((uint8_t *)this->table_gU[p1u]) + this->table_gV[p1v]); |
147 | b = this->table_bU[p1u]; | 148 | b = this->table_bU[p1u]; |
148 | 149 | ||
149 | *dst++ = r[p1y] + g[p1y] + b[p1y]; | 150 | *dst++ = r[p1y] + g[p1y] + b[p1y]; |
150 | p1y=*py++; | 151 | p1y=*py++; |
151 | *dst++ = r[p1y] + g[p1y] + b[p1y]; | 152 | *dst++ = r[p1y] + g[p1y] + b[p1y]; |
152 | 153 | ||
153 | p1y=*py2++; | 154 | p1y=*py2++; |
154 | 155 | ||
155 | *dst2++ = r[p1y] + g[p1y] + b[p1y]; | 156 | *dst2++ = r[p1y] + g[p1y] + b[p1y]; |
156 | p1y=*py2++; | 157 | p1y=*py2++; |
157 | *dst2++ = r[p1y] + g[p1y] + b[p1y]; | 158 | *dst2++ = r[p1y] + g[p1y] + b[p1y]; |
158 | } | 159 | } |
159 | _dst += (this->rgb_stride)<<1; | 160 | _dst += (this->rgb_stride)<<1; |
160 | _py += (this->y_stride)<<1; | 161 | _py += (this->y_stride)<<1; |
161 | _pu += this->uv_stride; | 162 | _pu += this->uv_stride; |
162 | _pv += this->uv_stride; | 163 | _pv += this->uv_stride; |
163 | } | 164 | } |
164 | } | 165 | } |
165 | 166 | ||
166 | 167 | ||
167 | /* Function: */ | 168 | /* Function: */ |
168 | static void arm_rgb16_step_dx_inf_32768(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) | 169 | static void arm_rgb16_step_dx_inf_32768(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) |
169 | /* This function is called when the destination picture is bigger than the size | 170 | /* This function is called when the destination picture is bigger than the size |
170 | of the source picture. | 171 | of the source picture. |
171 | */ | 172 | */ |
172 | { | 173 | { |
173 | int recal_uv, height; /* Note about recal_uv: bit0 is for | 174 | int recal_uv, height; /* Note about recal_uv: bit0 is for |
174 | applying scale on u and v, bit1 is for increments of u and v pointers.*/ | 175 | applying scale on u and v, bit1 is for increments of u and v pointers.*/ |
175 | int dy; | 176 | int dy; |
176 | 177 | ||
177 | dy = 0; | 178 | dy = 0; |
178 | height = this->dest_height; | 179 | height = this->dest_height; |
179 | recal_uv=1; // 1 for evaluation of scale_line, needed the first time | 180 | recal_uv=1; // 1 for evaluation of scale_line, needed the first time |
180 | 181 | ||
181 | while(1) | 182 | while(1) |
182 | { | 183 | { |
183 | register int dxy; | 184 | register int dxy; |
184 | register int dxuv; | 185 | register int dxuv; |
185 | register uint8_t p1y, p2y; | 186 | register uint8_t p1y, p2y; |
186 | uint8_t dest1y, dest2y; | 187 | uint8_t dest1y, dest2y; |
187 | register uint8_t p1u, p2u; | 188 | register uint8_t p1u, p2u; |
188 | register uint8_t p1v, p2v; | 189 | register uint8_t p1v, p2v; |
189 | uint8_t dest1u; | 190 | uint8_t dest1u; |
190 | uint8_t dest1v; | 191 | uint8_t dest1v; |
191 | int width; | 192 | int width; |
192 | uint8_t *u_buffer; | 193 | uint8_t *u_buffer; |
193 | uint8_t *v_buffer; | 194 | uint8_t *v_buffer; |
194 | uint16_t *r, *g, *b; | 195 | uint16_t *r, *g, *b; |
195 | uint8_t *py, *pu, *pv; | 196 | uint8_t *py, *pu, *pv; |
196 | uint16_t *dst; | 197 | uint16_t *dst; |
197 | 198 | ||
198 | dxy = 0; | 199 | dxy = 0; |
199 | dxuv = 0; | 200 | dxuv = 0; |
200 | width = this->dest_width; | 201 | width = this->dest_width; |
201 | u_buffer=this->u_buffer; | 202 | u_buffer=this->u_buffer; |
202 | v_buffer=this->v_buffer; | 203 | v_buffer=this->v_buffer; |
203 | dst = (uint16_t*)_dst; | 204 | dst = (uint16_t*)_dst; |
204 | py = _py; | 205 | py = _py; |
205 | pu = _pu; | 206 | pu = _pu; |
206 | pv = _pv; | 207 | pv = _pv; |
207 | 208 | ||
208 | //proceed with line scaling/conversion | 209 | //proceed with line scaling/conversion |
209 | if ((recal_uv&1)!=0) | 210 | if ((recal_uv&1)!=0) |
210 | { | 211 | { |
211 | recal_uv^=1; //reset bit0. | 212 | recal_uv^=1; //reset bit0. |
212 | // init values: | 213 | // init values: |
213 | p1u = *pu++; | 214 | p1u = *pu++; |
214 | p2u = *pu++; | 215 | p2u = *pu++; |
215 | p1v = *pv++; | 216 | p1v = *pv++; |
216 | p2v = *pv++; | 217 | p2v = *pv++; |
217 | p1y = *py++; | 218 | p1y = *py++; |
218 | p2y = *py++; | 219 | p2y = *py++; |
219 | 220 | ||
220 | //width loop (compute all data for a line). | 221 | //width loop (compute all data for a line). |
221 | while (width>0) | 222 | while (width>0) |
222 | { | 223 | { |
223 | // proceed with u and v first (ok, and y too finally :)) [scaling part]: | 224 | // proceed with u and v first (ok, and y too finally :)) [scaling part]: |
224 | // evaluate 1u, 1v, and 2y | 225 | // evaluate 1u, 1v, and 2y |
225 | //block1_uvy | 226 | //block1_uvy |
226 | dest1u=p1u + ((dxuv*(p2u-p1u))>>15); | 227 | dest1u=p1u + ((dxuv*(p2u-p1u))>>15); |
227 | dest1v=p1v + ((dxuv*(p2v-p1v))>>15); | 228 | dest1v=p1v + ((dxuv*(p2v-p1v))>>15); |
228 | // as u and v are evaluated, better save them now | 229 | // as u and v are evaluated, better save them now |
229 | *u_buffer++ = (uint8_t)dest1u; | 230 | *u_buffer++ = (uint8_t)dest1u; |
230 | *v_buffer++ = (uint8_t)dest1v; | 231 | *v_buffer++ = (uint8_t)dest1v; |
231 | 232 | ||
232 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); | 233 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); |
233 | 234 | ||
234 | dxuv += this->step_dx; | 235 | dxuv += this->step_dx; |
235 | dxy += this->step_dx; | 236 | dxy += this->step_dx; |
236 | if (dxuv > 32768) | 237 | if (dxuv > 32768) |
237 | { | 238 | { |
238 | dxuv -= 32768; | 239 | dxuv -= 32768; |
239 | p1u = p2u; | 240 | p1u = p2u; |
240 | p2u = *pu++; //idee pour asm, cf cas then, un merge est possible!!! | 241 | p2u = *pu++; //idee pour asm, cf cas then, un merge est possible!!! |
241 | p1v = p2v; | 242 | p1v = p2v; |
242 | p2v = *pv++; | 243 | p2v = *pv++; |
243 | } | 244 | } |
244 | if (dxy > 32768) | 245 | if (dxy > 32768) |
245 | { | 246 | { |
246 | dxy -= 32768; | 247 | dxy -= 32768; |
247 | p1y = p2y; | 248 | p1y = p2y; |
248 | p2y = *py++; | 249 | p2y = *py++; |
249 | } | 250 | } |
250 | //end block1_uvy | 251 | //end block1_uvy |
251 | 252 | ||
252 | //block2_y | 253 | //block2_y |
253 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); | 254 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); |
254 | 255 | ||
255 | dxy += this->step_dx; | 256 | dxy += this->step_dx; |
256 | if (dxy > 32768) | 257 | if (dxy > 32768) |
257 | { | 258 | { |
258 | dxy -= 32768; | 259 | dxy -= 32768; |
259 | p1y = p2y; | 260 | p1y = p2y; |
260 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! | 261 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! |
261 | } | 262 | } |
262 | //end block2_y | 263 | //end block2_y |
263 | 264 | ||
264 | // proceed now with YUV2RGB [conversion part]: | 265 | // proceed now with YUV2RGB [conversion part]: |
265 | // u and v are currently in dest1u and dest1v | 266 | // u and v are currently in dest1u and dest1v |
266 | // the 2 y are in dest1y and dest2y. | 267 | // the 2 y are in dest1y and dest2y. |
267 | // RGB(0),DST1(0), RGB(1), DST1(1) | 268 | // RGB(0),DST1(0), RGB(1), DST1(1) |
268 | r = this->table_rV[dest1v]; | 269 | r = this->table_rV[dest1v]; |
269 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); | 270 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); |
270 | b = this->table_bU[dest1u]; | 271 | b = this->table_bU[dest1u]; |
271 | 272 | ||
272 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; | 273 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; |
273 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; | 274 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; |
274 | 275 | ||
275 | width -=2; | 276 | width -=2; |
276 | } | 277 | } |
277 | } | 278 | } |
278 | else | 279 | else |
279 | { | 280 | { |
280 | // this case is simple, u and v are already evaluated, | 281 | // this case is simple, u and v are already evaluated, |
281 | // Note pour moi: r, g et b pourraient etre reutilises!! | 282 | // Note pour moi: r, g et b pourraient etre reutilises!! |
282 | 283 | ||
283 | // init values: | 284 | // init values: |
284 | p1y = *py++; | 285 | p1y = *py++; |
285 | p2y = *py++; | 286 | p2y = *py++; |
286 | 287 | ||
287 | //width loop (compute all data for a line). | 288 | //width loop (compute all data for a line). |
288 | while (width>0) | 289 | while (width>0) |
289 | { | 290 | { |
290 | // proceed with y [scaling part]: | 291 | // proceed with y [scaling part]: |
291 | // evaluate 2y | 292 | // evaluate 2y |
292 | //block1_y | 293 | //block1_y |
293 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); | 294 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); |
294 | 295 | ||
295 | dxy += this->step_dx; | 296 | dxy += this->step_dx; |
296 | if (dxy > 32768) | 297 | if (dxy > 32768) |
297 | { | 298 | { |
298 | dxy -= 32768; | 299 | dxy -= 32768; |
299 | p1y = p2y; | 300 | p1y = p2y; |
300 | p2y = *py++; | 301 | p2y = *py++; |
301 | } | 302 | } |
302 | //end block1_uvy | 303 | //end block1_uvy |
303 | 304 | ||
304 | //block2_y | 305 | //block2_y |
305 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); | 306 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); |
306 | 307 | ||
307 | dxy += this->step_dx; | 308 | dxy += this->step_dx; |
308 | if (dxy > 32768) | 309 | if (dxy > 32768) |
309 | { | 310 | { |
310 | dxy -= 32768; | 311 | dxy -= 32768; |
311 | p1y = p2y; | 312 | p1y = p2y; |
312 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! | 313 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! |
313 | } | 314 | } |
314 | //end block2_y | 315 | //end block2_y |
315 | 316 | ||
316 | // proceed now with YUV2RGB [conversion part]: | 317 | // proceed now with YUV2RGB [conversion part]: |
317 | // u and v are currently in dest1u and dest1v | 318 | // u and v are currently in dest1u and dest1v |
318 | // the 2 y are in dest1y and dest2y. | 319 | // the 2 y are in dest1y and dest2y. |
319 | // RGB(0),DST1(0) | 320 | // RGB(0),DST1(0) |
320 | dest1u=*u_buffer++; | 321 | dest1u=*u_buffer++; |
321 | dest1v=*v_buffer++; | 322 | dest1v=*v_buffer++; |
322 | r = this->table_rV[dest1v]; | 323 | r = this->table_rV[dest1v]; |
323 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); | 324 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); |
324 | b = this->table_bU[dest1u]; | 325 | b = this->table_bU[dest1u]; |
325 | 326 | ||
326 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; | 327 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; |
327 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; | 328 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; |
328 | 329 | ||
329 | width -=2; | 330 | width -=2; |
330 | } | 331 | } |
331 | } | 332 | } |
332 | // end of line scaling/conversion | 333 | // end of line scaling/conversion |
333 | dy += this->step_dy; | 334 | dy += this->step_dy; |
334 | _dst += this->rgb_stride; | 335 | _dst += this->rgb_stride; |
335 | 336 | ||
336 | while (--height > 0 && dy < 32768) | 337 | while (--height > 0 && dy < 32768) |
337 | { | 338 | { |
338 | xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); // *2 because of int8 cast! | 339 | xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); // *2 because of int8 cast! |
339 | dy += this->step_dy; | 340 | dy += this->step_dy; |
340 | _dst += this->rgb_stride; | 341 | _dst += this->rgb_stride; |
341 | } | 342 | } |
342 | 343 | ||
343 | 344 | ||
344 | if (height <= 0) | 345 | if (height <= 0) |
345 | break; | 346 | break; |
346 | 347 | ||
347 | do | 348 | do |
348 | { | 349 | { |
349 | dy -= 32768; | 350 | dy -= 32768; |
350 | _py += this->y_stride; | 351 | _py += this->y_stride; |
351 | 352 | ||
352 | recal_uv^=2; /*bit 0 for reevaluation of scanline, bit 1 for offset.*/ | 353 | recal_uv^=2; /*bit 0 for reevaluation of scanline, bit 1 for offset.*/ |
353 | 354 | ||
354 | if ((recal_uv&2)==0) | 355 | if ((recal_uv&2)==0) |
355 | { | 356 | { |
356 | _pu += this->uv_stride; | 357 | _pu += this->uv_stride; |
357 | _pv += this->uv_stride; | 358 | _pv += this->uv_stride; |
358 | recal_uv|=1; // if update, then reevaluate scanline! | 359 | recal_uv|=1; // if update, then reevaluate scanline! |
359 | } | 360 | } |
360 | } | 361 | } |
361 | while( dy>=32768); | 362 | while( dy>=32768); |
362 | } | 363 | } |
363 | } | 364 | } |
364 | 365 | ||
365 | 366 | ||
366 | 367 | ||
367 | /* Function: */ | 368 | /* Function: */ |
368 | static void arm_rgb16_step_dx_32768(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) | 369 | static void arm_rgb16_step_dx_32768(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) |
369 | /* This function is called when the widht of the destination picture is the | 370 | /* This function is called when the widht of the destination picture is the |
370 | same as the size of the source picture. | 371 | same as the size of the source picture. |
371 | */ | 372 | */ |
372 | { | 373 | { |
373 | int recal_uv, height; | 374 | int recal_uv, height; |
374 | int dy; | 375 | int dy; |
375 | 376 | ||
376 | dy = 0; | 377 | dy = 0; |
377 | height=this->dest_height; | 378 | height=this->dest_height; |
378 | recal_uv=0; | 379 | recal_uv=0; |
379 | 380 | ||
380 | while (1) | 381 | while (1) |
381 | { | 382 | { |
382 | uint16_t *r, *g, *b; | 383 | uint16_t *r, *g, *b; |
383 | uint8_t *py, *pu, *pv; | 384 | uint8_t *py, *pu, *pv; |
384 | uint16_t *dst; | 385 | uint16_t *dst; |
385 | int width; | 386 | int width; |
386 | register uint8_t p1y, p1u, p1v; | 387 | register uint8_t p1y, p1u, p1v; |
387 | 388 | ||
388 | width=this->dest_width; | 389 | width=this->dest_width; |
389 | dst = (uint16_t*)_dst; | 390 | dst = (uint16_t*)_dst; |
390 | py = _py; | 391 | py = _py; |
391 | pu = _pu; | 392 | pu = _pu; |
392 | pv = _pv; | 393 | pv = _pv; |
393 | 394 | ||
394 | while (width>0) | 395 | while (width>0) |
395 | { | 396 | { |
396 | width-=2; | 397 | width-=2; |
397 | p1y=*py++; | 398 | p1y=*py++; |
398 | p1u=*pu++; | 399 | p1u=*pu++; |
399 | p1v=*pv++; | 400 | p1v=*pv++; |
400 | 401 | ||
401 | r = this->table_rV[p1v]; | 402 | r = this->table_rV[p1v]; |
402 | g = (void *) (((uint8_t *)this->table_gU[p1u]) + this->table_gV[p1v]); | 403 | g = (void *) (((uint8_t *)this->table_gU[p1u]) + this->table_gV[p1v]); |
403 | b = this->table_bU[p1u]; | 404 | b = this->table_bU[p1u]; |
404 | 405 | ||
405 | *dst++ = r[p1y] + g[p1y] + b[p1y]; | 406 | *dst++ = r[p1y] + g[p1y] + b[p1y]; |
406 | p1y=*py++; | 407 | p1y=*py++; |
407 | *dst++ = r[p1y] + g[p1y] + b[p1y]; | 408 | *dst++ = r[p1y] + g[p1y] + b[p1y]; |
408 | } | 409 | } |
409 | 410 | ||
410 | 411 | ||
411 | 412 | ||
412 | // end of line scaling/conversion | 413 | // end of line scaling/conversion |
413 | dy += this->step_dy; | 414 | dy += this->step_dy; |
414 | _dst += this->rgb_stride; | 415 | _dst += this->rgb_stride; |
415 | 416 | ||
416 | while (--height > 0 && dy < 32768) | 417 | while (--height > 0 && dy < 32768) |
417 | { | 418 | { |
418 | xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); // *2 because of int8 cast! | 419 | xine_fast_memcpy (_dst, (uint8_t*)_dst-this->rgb_stride, this->dest_width*2); // *2 because of int8 cast! |
419 | dy += this->step_dy; | 420 | dy += this->step_dy; |
420 | _dst += this->rgb_stride; | 421 | _dst += this->rgb_stride; |
421 | } | 422 | } |
422 | 423 | ||
423 | 424 | ||
424 | if (height <= 0) | 425 | if (height <= 0) |
425 | break; | 426 | break; |
426 | 427 | ||
427 | do | 428 | do |
428 | { | 429 | { |
429 | dy -= 32768; | 430 | dy -= 32768; |
430 | _py += this->y_stride; | 431 | _py += this->y_stride; |
431 | 432 | ||
432 | recal_uv^=2; /*bit 0 for reevaluation of scanline, bit 1 for offset.*/ | 433 | recal_uv^=2; /*bit 0 for reevaluation of scanline, bit 1 for offset.*/ |
433 | 434 | ||
434 | if ((recal_uv&2)==0) | 435 | if ((recal_uv&2)==0) |
435 | { | 436 | { |
436 | _pu += this->uv_stride; | 437 | _pu += this->uv_stride; |
437 | _pv += this->uv_stride; | 438 | _pv += this->uv_stride; |
438 | recal_uv|=1; // if update, then reevaluate scanline! | 439 | recal_uv|=1; // if update, then reevaluate scanline! |
439 | } | 440 | } |
440 | } | 441 | } |
441 | while( dy>=32768); | 442 | while( dy>=32768); |
442 | } | 443 | } |
443 | } | 444 | } |
444 | 445 | ||
445 | 446 | ||
446 | 447 | ||
447 | /* Function: */ | 448 | /* Function: */ |
448 | static void arm_rgb16_step_dx_bet_32768_65536(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) | 449 | static void arm_rgb16_step_dx_bet_32768_65536(yuv2rgb_t *this, uint8_t * _dst, uint8_t * _py, uint8_t * _pu, uint8_t * _pv) |
449 | /* This function is called when the destination picture is between the size | 450 | /* This function is called when the destination picture is between the size |
450 | of the source picture, and half its size. | 451 | of the source picture, and half its size. |
451 | */ | 452 | */ |
452 | { | 453 | { |
453 | int recal_uv, height; /* Note about recal_uv: bit0 is for | 454 | int recal_uv, height; /* Note about recal_uv: bit0 is for |
454 | applying scale on u and v, bit1 is for increments of u and v pointers.*/ | 455 | applying scale on u and v, bit1 is for increments of u and v pointers.*/ |
455 | int dy; | 456 | int dy; |
456 | 457 | ||
457 | dy = 0; | 458 | dy = 0; |
458 | height = this->dest_height; | 459 | height = this->dest_height; |
459 | recal_uv=1; // 1 for evaluation of scale_line, needed the first time | 460 | recal_uv=1; // 1 for evaluation of scale_line, needed the first time |
460 | 461 | ||
461 | while(1) | 462 | while(1) |
462 | { | 463 | { |
463 | register int dxy; | 464 | register int dxy; |
464 | register int dxuv; | 465 | register int dxuv; |
465 | register uint8_t p1y, p2y; | 466 | register uint8_t p1y, p2y; |
466 | uint8_t dest1y, dest2y; | 467 | uint8_t dest1y, dest2y; |
467 | register uint8_t p1u, p2u; | 468 | register uint8_t p1u, p2u; |
468 | register uint8_t p1v, p2v; | 469 | register uint8_t p1v, p2v; |
469 | uint8_t dest1u; | 470 | uint8_t dest1u; |
470 | uint8_t dest1v; | 471 | uint8_t dest1v; |
471 | int width; | 472 | int width; |
472 | uint8_t *u_buffer; | 473 | uint8_t *u_buffer; |
473 | uint8_t *v_buffer; | 474 | uint8_t *v_buffer; |
474 | uint16_t *r, *g, *b; | 475 | uint16_t *r, *g, *b; |
475 | uint8_t *py, *pu, *pv; | 476 | uint8_t *py, *pu, *pv; |
476 | uint16_t *dst; | 477 | uint16_t *dst; |
477 | 478 | ||
478 | dxy = 0; | 479 | dxy = 0; |
479 | dxuv = 0; | 480 | dxuv = 0; |
480 | width = this->dest_width; | 481 | width = this->dest_width; |
481 | u_buffer=this->u_buffer; | 482 | u_buffer=this->u_buffer; |
482 | v_buffer=this->v_buffer; | 483 | v_buffer=this->v_buffer; |
483 | dst = (uint16_t*)_dst; | 484 | dst = (uint16_t*)_dst; |
484 | py = _py; | 485 | py = _py; |
485 | pu = _pu; | 486 | pu = _pu; |
486 | pv = _pv; | 487 | pv = _pv; |
487 | 488 | ||
488 | //proceed with line scaling/conversion | 489 | //proceed with line scaling/conversion |
489 | if ((recal_uv&1)!=0) | 490 | if ((recal_uv&1)!=0) |
490 | { | 491 | { |
491 | recal_uv^=1; //reset bit0. | 492 | recal_uv^=1; //reset bit0. |
492 | // init values: | 493 | // init values: |
493 | p1u = *pu++; | 494 | p1u = *pu++; |
494 | p2u = *pu++; | 495 | p2u = *pu++; |
495 | p1v = *pv++; | 496 | p1v = *pv++; |
496 | p2v = *pv++; | 497 | p2v = *pv++; |
497 | p1y = *py++; | 498 | p1y = *py++; |
498 | p2y = *py++; | 499 | p2y = *py++; |
499 | 500 | ||
500 | //width loop (compute all data for a line). | 501 | //width loop (compute all data for a line). |
501 | while (width>0) | 502 | while (width>0) |
502 | { | 503 | { |
503 | // proceed with u and v first (ok, and y too finally :)) [scaling part]: | 504 | // proceed with u and v first (ok, and y too finally :)) [scaling part]: |
504 | // evaluate 1u, 1v, and 2y | 505 | // evaluate 1u, 1v, and 2y |
505 | //block1_uvy | 506 | //block1_uvy |
506 | dest1u=p1u + ((dxuv*(p2u-p1u))>>15); | 507 | dest1u=p1u + ((dxuv*(p2u-p1u))>>15); |
507 | dest1v=p1v + ((dxuv*(p2v-p1v))>>15); | 508 | dest1v=p1v + ((dxuv*(p2v-p1v))>>15); |
508 | // as u and v are evaluated, better save them now | 509 | // as u and v are evaluated, better save them now |
509 | *u_buffer++ = (uint8_t)dest1u; | 510 | *u_buffer++ = (uint8_t)dest1u; |
510 | *v_buffer++ = (uint8_t)dest1v; | 511 | *v_buffer++ = (uint8_t)dest1v; |
511 | 512 | ||
512 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); | 513 | dest1y=p1y + ((dxy*(p2y-p1y))>>15); |
513 | 514 | ||
514 | dxuv += this->step_dx; | 515 | dxuv += this->step_dx; |
515 | dxy += this->step_dx; | 516 | dxy += this->step_dx; |
516 | if (dxuv > 65536) | 517 | if (dxuv > 65536) |
517 | { | 518 | { |
518 | dxuv -= 65536; | 519 | dxuv -= 65536; |
519 | p1u = *pu++; | 520 | p1u = *pu++; |
520 | p2u = *pu++; | 521 | p2u = *pu++; |
521 | p1v = *pv++; | 522 | p1v = *pv++; |
522 | p2v = *pv++; | 523 | p2v = *pv++; |
523 | } | 524 | } |
524 | else | 525 | else |
525 | { | 526 | { |
526 | dxuv -= 32768; | 527 | dxuv -= 32768; |
527 | p1u = p2u; | 528 | p1u = p2u; |
528 | p2u = *pu++; //idee pour asm, cf cas then, un merge est possible!!! | 529 | p2u = *pu++; //idee pour asm, cf cas then, un merge est possible!!! |
529 | p1v = p2v; | 530 | p1v = p2v; |
530 | p2v = *pv++; | 531 | p2v = *pv++; |
531 | } | 532 | } |
532 | if (dxy > 65536) | 533 | if (dxy > 65536) |
533 | { | 534 | { |
534 | dxy -= 65536; | 535 | dxy -= 65536; |
535 | p1y = *py++; | 536 | p1y = *py++; |
536 | p2y = *py++; | 537 | p2y = *py++; |
537 | } | 538 | } |
538 | else | 539 | else |
539 | { | 540 | { |
540 | dxy -= 32768; | 541 | dxy -= 32768; |
541 | p1y = p2y; | 542 | p1y = p2y; |
542 | p2y = *py++; | 543 | p2y = *py++; |
543 | } | 544 | } |
544 | //end block1_uvy | 545 | //end block1_uvy |
545 | 546 | ||
546 | //block2_y | 547 | //block2_y |
547 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); | 548 | dest2y=p1y + ((dxy*(p2y-p1y))>>15); |
548 | 549 | ||
549 | dxy += this->step_dx; | 550 | dxy += this->step_dx; |
550 | if (dxy > 65536) | 551 | if (dxy > 65536) |
551 | { | 552 | { |
552 | dxy -= 65536; | 553 | dxy -= 65536; |
553 | p1y = *py++; | 554 | p1y = *py++; |
554 | p2y = *py++; | 555 | p2y = *py++; |
555 | } | 556 | } |
556 | else | 557 | else |
557 | { | 558 | { |
558 | dxy -= 32768; | 559 | dxy -= 32768; |
559 | p1y = p2y; | 560 | p1y = p2y; |
560 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! | 561 | p2y = *py++; // idee pour asm, cf cas then, un merge est possible!!! |
561 | } | 562 | } |
562 | //end block2_y | 563 | //end block2_y |
563 | 564 | ||
564 | // proceed now with YUV2RGB [conversion part]: | 565 | // proceed now with YUV2RGB [conversion part]: |
565 | // u and v are currently in dest1u and dest1v | 566 | // u and v are currently in dest1u and dest1v |
566 | // the 2 y are in dest1y and dest2y. | 567 | // the 2 y are in dest1y and dest2y. |
567 | // RGB(0),DST1(0), RGB(1), DST1(1) | 568 | // RGB(0),DST1(0), RGB(1), DST1(1) |
568 | r = this->table_rV[dest1v]; | 569 | r = this->table_rV[dest1v]; |
569 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); | 570 | g = (void *) (((uint8_t *)this->table_gU[dest1u]) + this->table_gV[dest1v]); |
570 | b = this->table_bU[dest1u]; | 571 | b = this->table_bU[dest1u]; |
571 | 572 | ||
572 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; | 573 | *dst++ = r[dest1y] + g[dest1y] + b[dest1y]; |
573 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; | 574 | *dst++ = r[dest2y] + g[dest2y] + b[dest2y]; |
574 | 575 | ||
575 | width -=2; | 576 | width -=2; |
576 | } | 577 | } |
577 | } | 578 | } |
578 | else | 579 | else |
579 | { | 580 | { |
580 | // this case is simple, u and v are already evaluated, | 581 | // this case is simple, u and v are already evaluated, |
581 | // Note pour moi: r, g et b pourraient etre reutilises!! | 582 | // Note pour moi: r, g et b pourraient etre reutilises!! |
582 | 583 | ||