00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "mmsgui/fb/mmsfbconv.h"
00034
00035 #ifdef __HAVE_PF_YV12__
00036
00037 #include "mmstools/mmstools.h"
00038
00039 #ifdef __HAVE_SWSCALE__
00040 extern "C" {
00041 #include <libswscale/swscale.h>
00042 }
00043 #endif
00044
00045 void mmsfb_stretchblit_yv12_to_yv12(MMSFBSurfacePlanes *src_planes, int src_height, int sx, int sy, int sw, int sh,
00046 MMSFBSurfacePlanes *dst_planes, int dst_height, int dx, int dy, int dw, int dh,
00047 bool antialiasing) {
00048
00049 static bool firsttime = true;
00050 if (firsttime) {
00051 printf("DISKO: Using accelerated stretch YV12 to YV12.\n");
00052 firsttime = false;
00053 }
00054
00055
00056
00057
00058
00059
00060 #ifdef __HAVE_SWSCALE__
00061 static int fff = 0;
00062 #endif
00063 static int testswitchtime = 0;
00064 static int testswitch = 0;
00065 if (!testswitchtime) {
00066 testswitchtime=time(NULL)+30;
00067 #ifdef __HAVE_SWSCALE__
00068 printf(">>> using disko stretchblit YV12\n");
00069 #endif
00070 }
00071 else
00072 if (testswitchtime < time(NULL)) {
00073 testswitchtime=time(NULL)+30;
00074 testswitch++;
00075 if (testswitch > 11)
00076 testswitch = 0;
00077 #ifdef __HAVE_SWSCALE__
00078 switch (testswitch) {
00079 case 0:
00080 printf(">>> using disko stretchblit YV12\n");
00081 break;
00082 case 1:
00083 fff = SWS_POINT;
00084 printf(">>> using SWSCALE stretchblit flag=SWS_POINT\n");
00085 break;
00086 case 2:
00087 fff = SWS_AREA;
00088 printf(">>> using SWSCALE stretchblit flag=SWS_AREA\n");
00089 break;
00090 case 3:
00091 fff = SWS_BILINEAR;
00092 printf(">>> using SWSCALE stretchblit flag=SWS_BILINEAR\n");
00093 break;
00094 case 4:
00095 fff = SWS_FAST_BILINEAR;
00096 printf(">>> using SWSCALE stretchblit flag=SWS_FAST_BILINEAR\n");
00097 break;
00098 case 5:
00099 fff = SWS_BICUBIC;
00100 printf(">>> using SWSCALE stretchblit flag=SWS_BICUBIC\n");
00101 break;
00102 case 6:
00103 fff = SWS_X;
00104 printf(">>> using SWSCALE stretchblit flag=SWS_X\n");
00105 break;
00106 case 7:
00107 fff = SWS_GAUSS;
00108 printf(">>> using SWSCALE stretchblit flag=SWS_GAUSS\n");
00109 break;
00110 case 8:
00111 fff = SWS_LANCZOS;
00112 printf(">>> using SWSCALE stretchblit flag=SWS_LANCZOS\n");
00113 break;
00114 case 9:
00115 fff = SWS_SINC;
00116 printf(">>> using SWSCALE stretchblit flag=SWS_SINC\n");
00117 break;
00118 case 10:
00119 fff = SWS_SPLINE;
00120 printf(">>> using SWSCALE stretchblit flag=SWS_SPLINE\n");
00121 break;
00122 case 11:
00123 fff = SWS_BICUBLIN;
00124 printf(">>> using SWSCALE stretchblit flag=SWS_BICUBLIN\n");
00125 break;
00126 }
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 #endif
00146 }
00147 if (testswitch > 0) {
00148
00149 #ifdef __HAVE_SWSCALE__
00150
00151 if ((sx == 0 && dx == 0)
00152 &&(src_planes->pitch == sw && src_height >= (sy + sh))
00153 &&(dst_planes->pitch == dw && dst_height >= (dy + dh))) {
00154
00155
00156
00157
00158
00159 static SwsContext *sws_context = NULL;
00160 if (!sws_context) {
00161 const char *license = swscale_license();
00162 printf("DISKO: Using libswscale with license %s\n", license);
00163 }
00164
00165
00166 if (sy & 0x01) {
00167 sy++;
00168 sh--;
00169 }
00170 if (dy & 0x01) {
00171 dy++;
00172 dh--;
00173 }
00174 sh = sh & ~0x01;
00175 dh = dh & ~0x01;
00176
00177
00178 int pix_src_width = src_planes->pitch;
00179 int pix_src_height = sh;
00180 int pix_dst_width = dst_planes->pitch;
00181 int pix_dst_height = dh;
00182 int src_yoffs = sy * src_planes->pitch;
00183 int dst_yoffs = dy * dst_planes->pitch;
00184 int flags = fff;
00185
00186
00187
00188
00189
00190 sws_context = sws_getCachedContext( sws_context,
00191 pix_src_width, pix_src_height, PIX_FMT_YUV420P,
00192 pix_dst_width, pix_dst_height, PIX_FMT_YUV420P,
00193 flags, NULL, NULL, NULL);
00194 if (!sws_context) {
00195
00196 printf("DISKO: Failed to get SwsContext, using YV12 stretch blit fall back\n");
00197 }
00198 else {
00199
00200 int sws_src_stride[3];
00201 sws_src_stride[0] = src_planes->pitch;
00202 sws_src_stride[1] = sws_src_stride[2] = src_planes->pitch/2;
00203
00204
00205 int sws_dst_stride[3];
00206 sws_dst_stride[0] = dst_planes->pitch;
00207 sws_dst_stride[1] = sws_dst_stride[2] = dst_planes->pitch/2;
00208
00209
00210 uint8_t* sws_src[3];
00211 sws_src[0] = (uint8_t*)src_planes->ptr;
00212 if (!src_planes->ptr2) {
00213
00214 sws_src[2] = sws_src[0] + src_planes->pitch * src_height;
00215 sws_src[1] = sws_src[2] + src_planes->pitch * src_height / 4;
00216 }
00217 else {
00218
00219 sws_src[2] = (uint8_t*)src_planes->ptr2;
00220 sws_src[1] = (uint8_t*)src_planes->ptr3;
00221 }
00222
00223
00224 sws_src[0] = sws_src[0] + src_yoffs;
00225 sws_src[1] = sws_src[1] + (src_yoffs >> 2);
00226 sws_src[2] = sws_src[2] + (src_yoffs >> 2);
00227
00228
00229 uint8_t* sws_dst[3];
00230 sws_dst[0] = (uint8_t*)dst_planes->ptr;
00231 if (!dst_planes->ptr2) {
00232
00233 sws_dst[2] = sws_dst[0] + dst_planes->pitch * dst_height;
00234 sws_dst[1] = sws_dst[2] + dst_planes->pitch * dst_height / 4;
00235 }
00236 else {
00237
00238 sws_dst[2] = (uint8_t*)dst_planes->ptr2;
00239 sws_dst[1] = (uint8_t*)dst_planes->ptr3;
00240 }
00241
00242
00243 sws_dst[0] = sws_dst[0] + dst_yoffs;
00244 sws_dst[1] = sws_dst[1] + (dst_yoffs >> 2);
00245 sws_dst[2] = sws_dst[2] + (dst_yoffs >> 2);
00246
00247
00248 sws_scale( sws_context,
00249 sws_src, sws_src_stride, 0, pix_src_height,
00250 sws_dst, sws_dst_stride);
00251
00252
00253 return;
00254 }
00255 }
00256 #endif
00257
00258 }
00259
00260
00261
00262
00263
00264 unsigned char *src = (unsigned char *)src_planes->ptr;
00265 int src_pitch = src_planes->pitch;
00266
00267
00268 unsigned char *dst = (unsigned char *)dst_planes->ptr;
00269 int dst_pitch = dst_planes->pitch;
00270
00271
00272 int src_pitch_pix = src_pitch;
00273 int src_pitch_pix_half = src_pitch_pix >> 1;
00274 int dst_pitch_pix = dst_pitch;
00275 int dst_pitch_pix_half = dst_pitch_pix >> 1;
00276
00277
00278 if ((sw <= 0)||(sh <= 0))
00279 return;
00280
00281
00282 bool src_odd_left = (sx & 0x01);
00283 bool src_odd_top = (sy & 0x01);
00284 bool src_odd_right = ((sx + sw) & 0x01);
00285 bool src_odd_bottom = ((sy + sh) & 0x01);
00286 bool dst_odd_left = (dx & 0x01);
00287 bool dst_odd_top = (dy & 0x01);
00288 bool dst_odd_right = ((dx + dw) & 0x01);
00289 bool dst_odd_bottom = ((dy + dh) & 0x01);
00290
00291
00292 unsigned char *src_y = src + sx + sy * src_pitch_pix;
00293 unsigned char *src_u;
00294 unsigned char *src_v;
00295 if ((src_planes->ptr2)&&(src_planes->ptr3)) {
00296 src_u = (unsigned char *)src_planes->ptr3 + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00297 src_v = (unsigned char *)src_planes->ptr2 + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00298 }
00299 else {
00300 src_u = src + src_pitch_pix * src_height + src_pitch_pix_half * (src_height >> 1) + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00301 src_v = src + src_pitch_pix * src_height + (sx >> 1) + (sy >> 1) * src_pitch_pix_half;
00302 }
00303
00304
00305 unsigned char *dst_y = dst + dx + dy * dst_pitch_pix;
00306 unsigned char *dst_u;
00307 unsigned char *dst_v;
00308 if ((dst_planes->ptr2)&&(dst_planes->ptr3)) {
00309 dst_u = (unsigned char *)dst_planes->ptr2 + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00310 dst_v = (unsigned char *)dst_planes->ptr3 + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00311 }
00312 else {
00313 dst_u = dst + dst_pitch_pix * dst_height + dst_pitch_pix_half * (dst_height >> 1) + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00314 dst_v = dst + dst_pitch_pix * dst_height + (dx >> 1) + (dy >> 1) * dst_pitch_pix_half;
00315 }
00316
00317
00318 bool h_antialiasing = false;
00319 bool v_antialiasing = false;
00320 if (antialiasing) {
00321 if (sw != dw)
00322 h_antialiasing = true;
00323 if (sh != dh)
00324 v_antialiasing = true;
00325 }
00326
00327
00328 if (src_odd_top) {
00329
00330 sy++;
00331 sh--;
00332 src_y+=src_pitch;
00333 src_u+=src_pitch >> 1;
00334 src_v+=src_pitch >> 1;
00335 }
00336 if (src_odd_bottom) {
00337
00338 src_height--;
00339 }
00340 if (src_odd_left) {
00341
00342 sx++;
00343 sw--;
00344 src_y++;
00345 src_u++;
00346 src_v++;
00347 }
00348 if (src_odd_right) {
00349
00350 sw--;
00351 }
00352
00353
00354 if (dst_odd_top) {
00355
00356 dy++;
00357 dh--;
00358 dst_y+=dst_pitch;
00359 dst_u+=dst_pitch >> 1;
00360 dst_v+=dst_pitch >> 1;
00361 }
00362 if (dst_odd_bottom) {
00363
00364 dst_height--;
00365 }
00366 if (dst_odd_left) {
00367
00368 dx++;
00369 dw--;
00370 dst_y++;
00371 dst_u++;
00372 dst_v++;
00373 }
00374 if (dst_odd_right) {
00375
00376 dw--;
00377 }
00378
00379
00380 if ((sw < 2)||(sh < 2)||(dw < 2)||(dh < 2))
00381 return;
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 stretch_byte_buffer(h_antialiasing, h_antialiasing,
00392 src_u, src_pitch >> 1, src_pitch_pix >> 1, src_height >> 1, sw >> 1, sh >> 1,
00393 dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00394 compress_2x2_matrix(dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh,
00395 dst_u, dst_pitch >> 1, dst_pitch_pix >> 1, dst_height >> 1, dw >> 1, dh >> 1);
00396
00397
00398
00399
00400 stretch_byte_buffer(h_antialiasing, h_antialiasing,
00401 src_v, src_pitch >> 1, src_pitch_pix >> 1, src_height >> 1, sw >> 1, sh >> 1,
00402 dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00403 compress_2x2_matrix(dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh,
00404 dst_v, dst_pitch >> 1, dst_pitch_pix >> 1, dst_height >> 1, dw >> 1, dh >> 1);
00405
00406
00407 stretch_byte_buffer(h_antialiasing, v_antialiasing,
00408 src_y, src_pitch, src_pitch_pix, src_height, sw, sh,
00409 dst_y, dst_pitch, dst_pitch_pix, dst_height, dw, dh);
00410 }
00411
00412 #endif