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 #include <vlc/vlc.h>
00028 #include <vlc/decoder.h>
00029 #include "vlc_filter.h"
00030
00031
00032
00033
00034 struct filter_sys_t
00035 {
00036 int i_dummy;
00037 };
00038
00039
00040
00041
00042 static int OpenFilter ( vlc_object_t * );
00043 static void CloseFilter( vlc_object_t * );
00044
00045
00046 static void Blend( filter_t *, picture_t *, picture_t *, picture_t *,
00047 int, int, int );
00048 static void BlendI420( filter_t *, picture_t *, picture_t *, picture_t *,
00049 int, int, int, int, int );
00050 static void BlendR16( filter_t *, picture_t *, picture_t *, picture_t *,
00051 int, int, int, int, int );
00052 static void BlendR24( filter_t *, picture_t *, picture_t *, picture_t *,
00053 int, int, int, int, int );
00054 static void BlendYUY2( filter_t *, picture_t *, picture_t *, picture_t *,
00055 int, int, int, int, int );
00056 static void BlendPalI420( filter_t *, picture_t *, picture_t *, picture_t *,
00057 int, int, int, int, int );
00058 static void BlendPalYUY2( filter_t *, picture_t *, picture_t *, picture_t *,
00059 int, int, int, int, int );
00060 static void BlendPalRV( filter_t *, picture_t *, picture_t *, picture_t *,
00061 int, int, int, int, int );
00062
00063
00064
00065
00066 vlc_module_begin();
00067 set_description( _("Video pictures blending") );
00068 set_capability( "video blending", 100 );
00069 set_callbacks( OpenFilter, CloseFilter );
00070 vlc_module_end();
00071
00072
00073
00074
00075 static int OpenFilter( vlc_object_t *p_this )
00076 {
00077 filter_t *p_filter = (filter_t*)p_this;
00078 filter_sys_t *p_sys;
00079
00080
00081
00082 if( ( p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','A') &&
00083 p_filter->fmt_in.video.i_chroma != VLC_FOURCC('Y','U','V','P') ) ||
00084 ( p_filter->fmt_out.video.i_chroma != VLC_FOURCC('I','4','2','0') &&
00085 p_filter->fmt_out.video.i_chroma != VLC_FOURCC('Y','U','Y','2') &&
00086 p_filter->fmt_out.video.i_chroma != VLC_FOURCC('Y','V','1','2') &&
00087 p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','1','6') &&
00088 p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','2','4') &&
00089 p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','3','2') ) )
00090 {
00091 return VLC_EGENERIC;
00092 }
00093
00094
00095 if( ( p_filter->p_sys = p_sys =
00096 (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL )
00097 {
00098 msg_Err( p_filter, "out of memory" );
00099 return VLC_EGENERIC;
00100 }
00101
00102
00103 p_filter->pf_video_blend = Blend;
00104
00105 msg_Dbg( p_filter, "chroma: %4.4s -> %4.4s",
00106 (char *)&p_filter->fmt_in.video.i_chroma,
00107 (char *)&p_filter->fmt_out.video.i_chroma );
00108
00109
00110 return VLC_SUCCESS;
00111 }
00112
00113
00114
00115
00116
00117
00118 static void Blend( filter_t *p_filter, picture_t *p_dst,
00119 picture_t *p_dst_orig, picture_t *p_src,
00120 int i_x_offset, int i_y_offset, int i_alpha )
00121 {
00122 int i_width, i_height;
00123
00124 i_width = __MIN((int)p_filter->fmt_out.video.i_visible_width - i_x_offset,
00125 (int)p_filter->fmt_in.video.i_visible_width);
00126
00127 i_height = __MIN((int)p_filter->fmt_out.video.i_visible_height -i_y_offset,
00128 (int)p_filter->fmt_in.video.i_visible_height);
00129
00130 if( i_width <= 0 || i_height <= 0 ) return;
00131
00132 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
00133 ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('I','4','2','0') ||
00134 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ) )
00135 {
00136 BlendI420( p_filter, p_dst, p_dst_orig, p_src,
00137 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00138 return;
00139 }
00140 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
00141 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') )
00142 {
00143 BlendYUY2( p_filter, p_dst, p_dst_orig, p_src,
00144 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00145 return;
00146 }
00147 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
00148 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') )
00149 {
00150 BlendR16( p_filter, p_dst, p_dst_orig, p_src,
00151 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00152 return;
00153 }
00154 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','A') &&
00155 ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','2','4') ||
00156 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','3','2') ) )
00157 {
00158 BlendR24( p_filter, p_dst, p_dst_orig, p_src,
00159 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00160 return;
00161 }
00162 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
00163 ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('I','4','2','0') ||
00164 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','1','2') ) )
00165 {
00166 BlendPalI420( p_filter, p_dst, p_dst_orig, p_src,
00167 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00168 return;
00169 }
00170 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
00171 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') )
00172 {
00173 BlendPalYUY2( p_filter, p_dst, p_dst_orig, p_src,
00174 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00175 return;
00176 }
00177 if( p_filter->fmt_in.video.i_chroma == VLC_FOURCC('Y','U','V','P') &&
00178 ( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') ||
00179 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','2','4') ||
00180 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','3','2') ) )
00181 {
00182 BlendPalRV( p_filter, p_dst, p_dst_orig, p_src,
00183 i_x_offset, i_y_offset, i_width, i_height, i_alpha );
00184 return;
00185 }
00186
00187 msg_Dbg( p_filter, "no matching alpha blending routine" );
00188 }
00189
00190 static void BlendI420( filter_t *p_filter, picture_t *p_dst,
00191 picture_t *p_dst_orig, picture_t *p_src,
00192 int i_x_offset, int i_y_offset,
00193 int i_width, int i_height, int i_alpha )
00194 {
00195 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00196 uint8_t *p_src1_y, *p_src2_y, *p_dst_y;
00197 uint8_t *p_src1_u, *p_src2_u, *p_dst_u;
00198 uint8_t *p_src1_v, *p_src2_v, *p_dst_v;
00199 uint8_t *p_trans;
00200 int i_x, i_y, i_trans;
00201 vlc_bool_t b_even_scanline = i_y_offset % 2;
00202
00203 i_dst_pitch = p_dst->p[Y_PLANE].i_pitch;
00204 p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset +
00205 p_filter->fmt_out.video.i_x_offset +
00206 p_dst->p[Y_PLANE].i_pitch *
00207 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00208 p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 +
00209 p_filter->fmt_out.video.i_x_offset/2 +
00210 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00211 p_dst->p[U_PLANE].i_pitch;
00212 p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 +
00213 p_filter->fmt_out.video.i_x_offset/2 +
00214 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00215 p_dst->p[V_PLANE].i_pitch;
00216
00217 i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
00218 p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset +
00219 p_filter->fmt_out.video.i_x_offset +
00220 p_dst_orig->p[Y_PLANE].i_pitch *
00221 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00222 p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 +
00223 p_filter->fmt_out.video.i_x_offset/2 +
00224 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00225 p_dst_orig->p[U_PLANE].i_pitch;
00226 p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 +
00227 p_filter->fmt_out.video.i_x_offset/2 +
00228 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00229 p_dst_orig->p[V_PLANE].i_pitch;
00230
00231 i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
00232 p_src2_y = p_src->p[Y_PLANE].p_pixels +
00233 p_filter->fmt_in.video.i_x_offset +
00234 p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00235 p_src2_u = p_src->p[U_PLANE].p_pixels +
00236 p_filter->fmt_in.video.i_x_offset/2 +
00237 p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00238 p_src2_v = p_src->p[V_PLANE].p_pixels +
00239 p_filter->fmt_in.video.i_x_offset/2 +
00240 p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00241
00242 p_trans = p_src->p[A_PLANE].p_pixels +
00243 p_filter->fmt_in.video.i_x_offset +
00244 p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00245
00246 #define MAX_TRANS 255
00247 #define TRANS_BITS 8
00248
00249
00250 for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
00251 p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch,
00252 p_src2_y += i_src2_pitch,
00253 p_dst_u += b_even_scanline ? i_dst_pitch/2 : 0,
00254 p_src1_u += b_even_scanline ? i_src1_pitch/2 : 0,
00255 p_src2_u += i_src2_pitch,
00256 p_dst_v += b_even_scanline ? i_dst_pitch/2 : 0,
00257 p_src1_v += b_even_scanline ? i_src1_pitch/2 : 0,
00258 p_src2_v += i_src2_pitch )
00259 {
00260 b_even_scanline = !b_even_scanline;
00261
00262
00263 for( i_x = 0; i_x < i_width; i_x++ )
00264 {
00265 i_trans = ( p_trans[i_x] * i_alpha ) / 255;
00266 if( !i_trans )
00267 {
00268
00269 continue;
00270 }
00271 else if( i_trans == MAX_TRANS )
00272 {
00273
00274 p_dst_y[i_x] = p_src2_y[i_x];
00275
00276 if( b_even_scanline && i_x % 2 == 0 )
00277 {
00278 p_dst_u[i_x/2] = p_src2_u[i_x];
00279 p_dst_v[i_x/2] = p_src2_v[i_x];
00280 }
00281 continue;
00282 }
00283
00284
00285 p_dst_y[i_x] = ( (uint16_t)p_src2_y[i_x] * i_trans +
00286 (uint16_t)p_src1_y[i_x] * (MAX_TRANS - i_trans) )
00287 >> TRANS_BITS;
00288
00289 if( b_even_scanline && i_x % 2 == 0 )
00290 {
00291 p_dst_u[i_x/2] = ( (uint16_t)p_src2_u[i_x] * i_trans +
00292 (uint16_t)p_src1_u[i_x/2] * (MAX_TRANS - i_trans) )
00293 >> TRANS_BITS;
00294 p_dst_v[i_x/2] = ( (uint16_t)p_src2_v[i_x] * i_trans +
00295 (uint16_t)p_src1_v[i_x/2] * (MAX_TRANS - i_trans) )
00296 >> TRANS_BITS;
00297 }
00298 }
00299 }
00300
00301 #undef MAX_TRANS
00302 #undef TRANS_BITS
00303
00304 return;
00305 }
00306
00307 static inline void yuv_to_rgb( int *r, int *g, int *b,
00308 uint8_t y1, uint8_t u1, uint8_t v1 )
00309 {
00310
00311 # define SCALEBITS 10
00312 # define ONE_HALF (1 << (SCALEBITS - 1))
00313 # define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
00314 # define CLAMP( x ) (((x) > 255) ? 255 : ((x) < 0) ? 0 : (x));
00315
00316 int y, cb, cr, r_add, g_add, b_add;
00317
00318 cb = u1 - 128;
00319 cr = v1 - 128;
00320 r_add = FIX(1.40200*255.0/224.0) * cr + ONE_HALF;
00321 g_add = - FIX(0.34414*255.0/224.0) * cb
00322 - FIX(0.71414*255.0/224.0) * cr + ONE_HALF;
00323 b_add = FIX(1.77200*255.0/224.0) * cb + ONE_HALF;
00324 y = (y1 - 16) * FIX(255.0/219.0);
00325 *r = CLAMP((y + r_add) >> SCALEBITS);
00326 *g = CLAMP((y + g_add) >> SCALEBITS);
00327 *b = CLAMP((y + b_add) >> SCALEBITS);
00328 }
00329
00330 static void BlendR16( filter_t *p_filter, picture_t *p_dst_pic,
00331 picture_t *p_dst_orig, picture_t *p_src,
00332 int i_x_offset, int i_y_offset,
00333 int i_width, int i_height, int i_alpha )
00334 {
00335 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00336 uint8_t *p_dst, *p_src1, *p_src2_y;
00337 uint8_t *p_src2_u, *p_src2_v;
00338 uint8_t *p_trans;
00339 int i_x, i_y, i_pix_pitch;
00340 int r, g, b;
00341
00342 i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
00343 i_dst_pitch = p_dst_pic->p->i_pitch;
00344 p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
00345 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00346 p_dst_pic->p->i_pitch *
00347 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00348
00349 i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
00350 p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
00351 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00352 p_dst_orig->p->i_pitch *
00353 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00354
00355 i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
00356 p_src2_y = p_src->p[Y_PLANE].p_pixels +
00357 p_filter->fmt_in.video.i_x_offset +
00358 p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00359 p_src2_u = p_src->p[U_PLANE].p_pixels +
00360 p_filter->fmt_in.video.i_x_offset/2 +
00361 p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00362 p_src2_v = p_src->p[V_PLANE].p_pixels +
00363 p_filter->fmt_in.video.i_x_offset/2 +
00364 p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00365
00366 p_trans = p_src->p[A_PLANE].p_pixels +
00367 p_filter->fmt_in.video.i_x_offset +
00368 p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00369
00370 #define MAX_TRANS 255
00371 #define TRANS_BITS 8
00372
00373
00374 for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
00375 p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
00376 p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
00377 p_src2_v += i_src2_pitch )
00378 {
00379
00380 for( i_x = 0; i_x < i_width; i_x++ )
00381 {
00382 if( !p_trans[i_x] )
00383 {
00384
00385 continue;
00386 }
00387 else if( p_trans[i_x] == MAX_TRANS )
00388 {
00389
00390 yuv_to_rgb( &r, &g, &b,
00391 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
00392
00393 ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
00394 continue;
00395 }
00396
00397
00398 yuv_to_rgb( &r, &g, &b,
00399 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
00400
00401 ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
00402 }
00403 }
00404
00405 #undef MAX_TRANS
00406 #undef TRANS_BITS
00407
00408 return;
00409 }
00410
00411 static void BlendR24( filter_t *p_filter, picture_t *p_dst_pic,
00412 picture_t *p_dst_orig, picture_t *p_src,
00413 int i_x_offset, int i_y_offset,
00414 int i_width, int i_height, int i_alpha )
00415 {
00416 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00417 uint8_t *p_dst, *p_src1, *p_src2_y;
00418 uint8_t *p_src2_u, *p_src2_v;
00419 uint8_t *p_trans;
00420 int i_x, i_y, i_pix_pitch, i_trans;
00421 int r, g, b;
00422
00423 i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
00424 i_dst_pitch = p_dst_pic->p->i_pitch;
00425 p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
00426 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00427 p_dst_pic->p->i_pitch *
00428 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00429
00430 i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
00431 p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
00432 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00433 p_dst_orig->p->i_pitch *
00434 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00435
00436 i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
00437 p_src2_y = p_src->p[Y_PLANE].p_pixels +
00438 p_filter->fmt_in.video.i_x_offset +
00439 p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00440 p_src2_u = p_src->p[U_PLANE].p_pixels +
00441 p_filter->fmt_in.video.i_x_offset/2 +
00442 p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00443 p_src2_v = p_src->p[V_PLANE].p_pixels +
00444 p_filter->fmt_in.video.i_x_offset/2 +
00445 p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00446
00447 p_trans = p_src->p[A_PLANE].p_pixels +
00448 p_filter->fmt_in.video.i_x_offset +
00449 p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00450
00451 #define MAX_TRANS 255
00452 #define TRANS_BITS 8
00453
00454
00455 for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
00456 p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
00457 p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
00458 p_src2_v += i_src2_pitch )
00459 {
00460
00461 for( i_x = 0; i_x < i_width; i_x++ )
00462 {
00463 i_trans = ( p_trans[i_x] * i_alpha ) / 255;
00464 if( !i_trans )
00465 {
00466
00467 continue;
00468 }
00469 else if( i_trans == MAX_TRANS )
00470 {
00471
00472 yuv_to_rgb( &r, &g, &b,
00473 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
00474
00475 p_dst[i_x * i_pix_pitch] = r;
00476 p_dst[i_x * i_pix_pitch + 1] = g;
00477 p_dst[i_x * i_pix_pitch + 2] = b;
00478 continue;
00479 }
00480
00481
00482 yuv_to_rgb( &r, &g, &b,
00483 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] );
00484
00485 p_dst[i_x * i_pix_pitch] = ( r * i_trans +
00486 (uint16_t)p_src1[i_x * i_pix_pitch] *
00487 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00488 p_dst[i_x * i_pix_pitch + 1] = ( g * i_trans +
00489 (uint16_t)p_src1[i_x * i_pix_pitch + 1] *
00490 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00491 p_dst[i_x * i_pix_pitch + 2] = ( b * i_trans +
00492 (uint16_t)p_src1[i_x * i_pix_pitch + 2] *
00493 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00494 }
00495 }
00496
00497 #undef MAX_TRANS
00498 #undef TRANS_BITS
00499
00500 return;
00501 }
00502
00503 static void BlendYUY2( filter_t *p_filter, picture_t *p_dst_pic,
00504 picture_t *p_dst_orig, picture_t *p_src,
00505 int i_x_offset, int i_y_offset,
00506 int i_width, int i_height, int i_alpha )
00507 {
00508 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00509 uint8_t *p_dst, *p_src1, *p_src2_y;
00510 uint8_t *p_src2_u, *p_src2_v;
00511 uint8_t *p_trans;
00512 int i_x, i_y, i_pix_pitch, i_trans;
00513 vlc_bool_t b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2);
00514
00515 i_pix_pitch = 2;
00516 i_dst_pitch = p_dst_pic->p->i_pitch;
00517 p_dst = p_dst_pic->p->p_pixels + i_x_offset * i_pix_pitch +
00518 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00519 p_dst_pic->p->i_pitch *
00520 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00521
00522 i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
00523 p_src1 = p_dst_orig->p->p_pixels + i_x_offset * i_pix_pitch +
00524 p_filter->fmt_out.video.i_x_offset * i_pix_pitch +
00525 p_dst_orig->p->i_pitch *
00526 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00527
00528 i_src2_pitch = p_src->p[Y_PLANE].i_pitch;
00529 p_src2_y = p_src->p[Y_PLANE].p_pixels +
00530 p_filter->fmt_in.video.i_x_offset +
00531 p_src->p[Y_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00532 p_src2_u = p_src->p[U_PLANE].p_pixels +
00533 p_filter->fmt_in.video.i_x_offset/2 +
00534 p_src->p[U_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00535 p_src2_v = p_src->p[V_PLANE].p_pixels +
00536 p_filter->fmt_in.video.i_x_offset/2 +
00537 p_src->p[V_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset/2;
00538
00539 p_trans = p_src->p[A_PLANE].p_pixels +
00540 p_filter->fmt_in.video.i_x_offset +
00541 p_src->p[A_PLANE].i_pitch * p_filter->fmt_in.video.i_y_offset;
00542
00543 i_width = (i_width >> 1) << 1;
00544
00545 #define MAX_TRANS 255
00546 #define TRANS_BITS 8
00547
00548
00549 for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch,
00550 p_dst += i_dst_pitch, p_src1 += i_src1_pitch,
00551 p_src2_y += i_src2_pitch, p_src2_u += i_src2_pitch,
00552 p_src2_v += i_src2_pitch )
00553 {
00554
00555 for( i_x = 0; i_x < i_width; i_x++, b_even = !b_even )
00556 {
00557 i_trans = ( p_trans[i_x] * i_alpha ) / 255;
00558 if( !i_trans )
00559 {
00560
00561 }
00562 else if( i_trans == MAX_TRANS )
00563 {
00564
00565 p_dst[i_x * 2] = p_src2_y[i_x];
00566
00567 if( b_even )
00568 {
00569 p_dst[i_x * 2 + 1] = p_src2_u[i_x];
00570 p_dst[i_x * 2 + 3] = p_src2_v[i_x];
00571 }
00572 }
00573 else
00574 {
00575
00576 p_dst[i_x * 2] = ( (uint16_t)p_src2_y[i_x] * i_trans +
00577 (uint16_t)p_src1[i_x * 2] * (MAX_TRANS - i_trans) )
00578 >> TRANS_BITS;
00579
00580 if( b_even )
00581 {
00582 p_dst[i_x * 2 + 1] = ( (uint16_t)p_src2_u[i_x] * i_trans +
00583 (uint16_t)p_src1[i_x * 2 + 1] * (MAX_TRANS - i_trans) )
00584 >> TRANS_BITS;
00585 p_dst[i_x * 2 + 3] = ( (uint16_t)p_src2_v[i_x] * i_trans +
00586 (uint16_t)p_src1[i_x * 2 + 3] * (MAX_TRANS - i_trans) )
00587 >> TRANS_BITS;
00588 }
00589 }
00590 }
00591 }
00592
00593 #undef MAX_TRANS
00594 #undef TRANS_BITS
00595
00596 return;
00597 }
00598
00599 static void BlendPalI420( filter_t *p_filter, picture_t *p_dst,
00600 picture_t *p_dst_orig, picture_t *p_src,
00601 int i_x_offset, int i_y_offset,
00602 int i_width, int i_height, int i_alpha )
00603 {
00604 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00605 uint8_t *p_src1_y, *p_src2, *p_dst_y;
00606 uint8_t *p_src1_u, *p_dst_u;
00607 uint8_t *p_src1_v, *p_dst_v;
00608 int i_x, i_y, i_trans;
00609 vlc_bool_t b_even_scanline = i_y_offset % 2;
00610
00611 i_dst_pitch = p_dst->p[Y_PLANE].i_pitch;
00612 p_dst_y = p_dst->p[Y_PLANE].p_pixels + i_x_offset +
00613 p_filter->fmt_out.video.i_x_offset +
00614 p_dst->p[Y_PLANE].i_pitch *
00615 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00616 p_dst_u = p_dst->p[U_PLANE].p_pixels + i_x_offset/2 +
00617 p_filter->fmt_out.video.i_x_offset/2 +
00618 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00619 p_dst->p[U_PLANE].i_pitch;
00620 p_dst_v = p_dst->p[V_PLANE].p_pixels + i_x_offset/2 +
00621 p_filter->fmt_out.video.i_x_offset/2 +
00622 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00623 p_dst->p[V_PLANE].i_pitch;
00624
00625 i_src1_pitch = p_dst_orig->p[Y_PLANE].i_pitch;
00626 p_src1_y = p_dst_orig->p[Y_PLANE].p_pixels + i_x_offset +
00627 p_filter->fmt_out.video.i_x_offset +
00628 p_dst_orig->p[Y_PLANE].i_pitch *
00629 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00630 p_src1_u = p_dst_orig->p[U_PLANE].p_pixels + i_x_offset/2 +
00631 p_filter->fmt_out.video.i_x_offset/2 +
00632 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00633 p_dst_orig->p[U_PLANE].i_pitch;
00634 p_src1_v = p_dst_orig->p[V_PLANE].p_pixels + i_x_offset/2 +
00635 p_filter->fmt_out.video.i_x_offset/2 +
00636 ( i_y_offset + p_filter->fmt_out.video.i_y_offset ) / 2 *
00637 p_dst_orig->p[V_PLANE].i_pitch;
00638
00639 i_src2_pitch = p_src->p->i_pitch;
00640 p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
00641 i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
00642
00643 #define MAX_TRANS 255
00644 #define TRANS_BITS 8
00645 #define p_trans p_src2
00646 #define p_pal p_filter->fmt_in.video.p_palette->palette
00647
00648
00649 for( i_y = 0; i_y < i_height; i_y++,
00650 p_dst_y += i_dst_pitch, p_src1_y += i_src1_pitch,
00651 p_src2 += i_src2_pitch,
00652 p_dst_u += b_even_scanline ? i_dst_pitch/2 : 0,
00653 p_src1_u += b_even_scanline ? i_src1_pitch/2 : 0,
00654 p_dst_v += b_even_scanline ? i_dst_pitch/2 : 0,
00655 p_src1_v += b_even_scanline ? i_src1_pitch/2 : 0 )
00656 {
00657 b_even_scanline = !b_even_scanline;
00658
00659
00660 for( i_x = 0; i_x < i_width; i_x++ )
00661 {
00662 i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
00663 if( !i_trans )
00664 {
00665
00666 continue;
00667 }
00668 else if( i_trans == MAX_TRANS )
00669 {
00670
00671 p_dst_y[i_x] = p_pal[p_src2[i_x]][0];
00672
00673 if( b_even_scanline && i_x % 2 == 0 )
00674 {
00675 p_dst_u[i_x/2] = p_pal[p_src2[i_x]][1];
00676 p_dst_v[i_x/2] = p_pal[p_src2[i_x]][2];
00677 }
00678 continue;
00679 }
00680
00681
00682 p_dst_y[i_x] = ( (uint16_t)p_pal[p_src2[i_x]][0] * i_trans +
00683 (uint16_t)p_src1_y[i_x] * (MAX_TRANS - i_trans) )
00684 >> TRANS_BITS;
00685
00686 if( b_even_scanline && i_x % 2 == 0 )
00687 {
00688 p_dst_u[i_x/2] = ( (uint16_t)p_pal[p_src2[i_x]][1] * i_trans +
00689 (uint16_t)p_src1_u[i_x/2] * (MAX_TRANS - i_trans) )
00690 >> TRANS_BITS;
00691 p_dst_v[i_x/2] = ( (uint16_t)p_pal[p_src2[i_x]][2] * i_trans +
00692 (uint16_t)p_src1_v[i_x/2] * (MAX_TRANS - i_trans) )
00693 >> TRANS_BITS;
00694 }
00695 }
00696 }
00697
00698 #undef MAX_TRANS
00699 #undef TRANS_BITS
00700 #undef p_trans
00701 #undef p_pal
00702
00703 return;
00704 }
00705
00706 static void BlendPalYUY2( filter_t *p_filter, picture_t *p_dst_pic,
00707 picture_t *p_dst_orig, picture_t *p_src,
00708 int i_x_offset, int i_y_offset,
00709 int i_width, int i_height, int i_alpha )
00710 {
00711 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00712 uint8_t *p_src1, *p_src2, *p_dst;
00713 int i_x, i_y, i_pix_pitch, i_trans;
00714 vlc_bool_t b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2);
00715
00716 i_pix_pitch = 2;
00717 i_dst_pitch = p_dst_pic->p->i_pitch;
00718 p_dst = p_dst_pic->p->p_pixels + i_pix_pitch * (i_x_offset +
00719 p_filter->fmt_out.video.i_x_offset) + p_dst_pic->p->i_pitch *
00720 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00721
00722 i_src1_pitch = p_dst_orig->p->i_pitch;
00723 p_src1 = p_dst_orig->p->p_pixels + i_pix_pitch * (i_x_offset +
00724 p_filter->fmt_out.video.i_x_offset) + p_dst_orig->p->i_pitch *
00725 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00726
00727 i_src2_pitch = p_src->p->i_pitch;
00728 p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
00729 i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
00730
00731 i_width = (i_width >> 1) << 1;
00732
00733 #define MAX_TRANS 255
00734 #define TRANS_BITS 8
00735 #define p_trans p_src2
00736 #define p_pal p_filter->fmt_in.video.p_palette->palette
00737
00738
00739 for( i_y = 0; i_y < i_height; i_y++,
00740 p_dst += i_dst_pitch, p_src1 += i_src1_pitch, p_src2 += i_src2_pitch )
00741 {
00742
00743 for( i_x = 0; i_x < i_width; i_x++, b_even = !b_even )
00744 {
00745 i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
00746 if( !i_trans )
00747 {
00748
00749 }
00750 else if( i_trans == MAX_TRANS )
00751 {
00752
00753 p_dst[i_x * 2] = p_pal[p_src2[i_x]][0];
00754
00755 if( b_even )
00756 {
00757 p_dst[i_x * 2 + 1] = p_pal[p_src2[i_x]][1];
00758 p_dst[i_x * 2 + 3] = p_pal[p_src2[i_x]][2];
00759 }
00760 }
00761 else
00762 {
00763
00764 p_dst[i_x * 2] = ( (uint16_t)p_pal[p_src2[i_x]][0] *
00765 i_trans + (uint16_t)p_src1[i_x * 2] *
00766 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00767
00768 if( b_even )
00769 {
00770 p_dst[i_x * 2 + 1] = ( (uint16_t)p_pal[p_src2[i_x]][1] *
00771 i_trans + (uint16_t)p_src1[i_x * 2 + 1] *
00772 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00773 p_dst[i_x * 2 + 3] = ( (uint16_t)p_pal[p_src2[i_x]][2] *
00774 i_trans + (uint16_t)p_src1[i_x * 2 + 3] *
00775 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00776 }
00777 }
00778 }
00779 }
00780
00781 #undef MAX_TRANS
00782 #undef TRANS_BITS
00783 #undef p_trans
00784 #undef p_pal
00785
00786 return;
00787 }
00788
00789 static void BlendPalRV( filter_t *p_filter, picture_t *p_dst_pic,
00790 picture_t *p_dst_orig, picture_t *p_src,
00791 int i_x_offset, int i_y_offset,
00792 int i_width, int i_height, int i_alpha )
00793 {
00794 int i_src1_pitch, i_src2_pitch, i_dst_pitch;
00795 uint8_t *p_src1, *p_src2, *p_dst;
00796 int i_x, i_y, i_pix_pitch, i_trans;
00797 int r, g, b;
00798 video_palette_t rgbpalette;
00799
00800 i_pix_pitch = p_dst_pic->p->i_pixel_pitch;
00801 i_dst_pitch = p_dst_pic->p->i_pitch;
00802 p_dst = p_dst_pic->p->p_pixels + i_pix_pitch * (i_x_offset +
00803 p_filter->fmt_out.video.i_x_offset) + p_dst_pic->p->i_pitch *
00804 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00805
00806 i_src1_pitch = p_dst_orig->p->i_pitch;
00807 p_src1 = p_dst_orig->p->p_pixels + i_pix_pitch * (i_x_offset +
00808 p_filter->fmt_out.video.i_x_offset) + p_dst_orig->p->i_pitch *
00809 ( i_y_offset + p_filter->fmt_out.video.i_y_offset );
00810
00811 i_src2_pitch = p_src->p->i_pitch;
00812 p_src2 = p_src->p->p_pixels + p_filter->fmt_in.video.i_x_offset +
00813 i_src2_pitch * p_filter->fmt_in.video.i_y_offset;
00814
00815 #define MAX_TRANS 255
00816 #define TRANS_BITS 8
00817 #define p_trans p_src2
00818 #define p_pal p_filter->fmt_in.video.p_palette->palette
00819 #define rgbpal rgbpalette.palette
00820
00821
00822 for( i_y = 0; i_y < p_filter->fmt_in.video.p_palette->i_entries &&
00823 i_y < 256; i_y++ )
00824 {
00825 yuv_to_rgb( &r, &g, &b, p_pal[i_y][0], p_pal[i_y][1], p_pal[i_y][2] );
00826
00827 if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') )
00828 {
00829 *(uint16_t *)rgbpal[i_y] =
00830 ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
00831 }
00832 else
00833 {
00834 rgbpal[i_y][0] = r; rgbpal[i_y][1] = g; rgbpal[i_y][2] = b;
00835 }
00836 }
00837
00838
00839 for( i_y = 0; i_y < i_height; i_y++,
00840 p_dst += i_dst_pitch, p_src1 += i_src1_pitch, p_src2 += i_src2_pitch )
00841 {
00842
00843 for( i_x = 0; i_x < i_width; i_x++ )
00844 {
00845 i_trans = ( p_pal[p_trans[i_x]][3] * i_alpha ) / 255;
00846 if( !i_trans )
00847 {
00848
00849 continue;
00850 }
00851 else if( i_trans == MAX_TRANS ||
00852 p_filter->fmt_out.video.i_chroma ==
00853 VLC_FOURCC('R','V','1','6') )
00854 {
00855
00856 p_dst[i_x * i_pix_pitch] = rgbpal[p_src2[i_x]][0];
00857 p_dst[i_x * i_pix_pitch + 1] = rgbpal[p_src2[i_x]][1];
00858 if( p_filter->fmt_out.video.i_chroma !=
00859 VLC_FOURCC('R','V','1','6') )
00860 p_dst[i_x * i_pix_pitch + 2] = rgbpal[p_src2[i_x]][2];
00861 continue;
00862 }
00863
00864
00865 p_dst[i_x * i_pix_pitch] = ( (uint16_t)rgbpal[p_src2[i_x]][0] *
00866 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch] *
00867 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00868 p_dst[i_x * i_pix_pitch + 1] = ( (uint16_t)rgbpal[p_src2[i_x]][1] *
00869 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch + 1] *
00870 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00871 p_dst[i_x * i_pix_pitch + 2] = ( (uint16_t)rgbpal[p_src2[i_x]][2] *
00872 i_trans + (uint16_t)p_src1[i_x * i_pix_pitch + 2] *
00873 (MAX_TRANS - i_trans) ) >> TRANS_BITS;
00874 }
00875 }
00876
00877 #undef MAX_TRANS
00878 #undef TRANS_BITS
00879 #undef p_trans
00880 #undef p_pal
00881 #undef rgbpal
00882
00883 return;
00884 }
00885
00886
00887
00888
00889 static void CloseFilter( vlc_object_t *p_this )
00890 {
00891 filter_t *p_filter = (filter_t*)p_this;
00892 filter_sys_t *p_sys = p_filter->p_sys;
00893
00894 free( p_sys );
00895 }