1 /*****************************************************************************
2 * swscale.c: scaling and chroma conversion using libswscale
3 *****************************************************************************
4 * Copyright (C) 1999-2008 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2.1 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
36 #include <vlc_picture.h>
39 #include <libswscale/swscale.h>
40 #include <libswscale/version.h>
43 # include <TargetConditionals.h>
46 #include "../codec/avcodec/chroma.h" // Chroma Avutil <-> VLC conversion
48 /* Gruikkkkkkkkkk!!!!! */
50 #define AVPALETTE_SIZE (256 * sizeof(uint32_t))
52 /*****************************************************************************
54 *****************************************************************************/
55 static int OpenScaler( vlc_object_t
* );
56 static void CloseScaler( vlc_object_t
* );
58 #define SCALEMODE_TEXT N_("Scaling mode")
59 #define SCALEMODE_LONGTEXT N_("Scaling mode to use.")
61 static const int pi_mode_values
[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
62 const char *const ppsz_mode_descriptions
[] =
63 { N_("Fast bilinear"), N_("Bilinear"), N_("Bicubic (good quality)"),
64 N_("Experimental"), N_("Nearest neighbour (bad quality)"),
65 N_("Area"), N_("Luma bicubic / chroma bilinear"), N_("Gauss"),
66 N_("SincR"), N_("Lanczos"), N_("Bicubic spline") };
69 set_description( N_("Video scaling filter") )
70 set_shortname( N_("Swscale" ) )
71 set_capability( "video converter", 150 )
72 set_category( CAT_VIDEO
)
73 set_subcategory( SUBCAT_VIDEO_VFILTER
)
74 set_callbacks( OpenScaler
, CloseScaler
)
75 add_integer( "swscale-mode", 2, SCALEMODE_TEXT
, SCALEMODE_LONGTEXT
, true )
76 change_integer_list( pi_mode_values
, ppsz_mode_descriptions
)
79 /* Version checking */
80 #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)
81 /****************************************************************************
83 ****************************************************************************/
86 * Internal swscale filter structure.
91 int i_cpu_mask
, i_sws_flags
;
93 video_format_t fmt_in
;
94 video_format_t fmt_out
;
95 const vlc_chroma_description_t
*desc_in
;
96 const vlc_chroma_description_t
*desc_out
;
98 struct SwsContext
*ctx
;
99 struct SwsContext
*ctxA
;
111 static picture_t
*Filter( filter_t
*, picture_t
* );
112 static int Init( filter_t
* );
113 static void Clean( filter_t
* );
125 } ScalerConfiguration
;
127 static int GetParameters( ScalerConfiguration
*,
128 const video_format_t
*p_fmti
,
129 const video_format_t
*p_fmto
,
130 int i_sws_flags_default
);
132 static int GetSwsCpuMask(void);
134 /* SwScaler point resize quality seems really bad, let our scale module do it
135 * (change it to true to try) */
136 #define ALLOW_YUVP (false)
137 /* SwScaler does not like too small picture */
138 #define MINIMUM_WIDTH (32)
140 /* XXX is it always 3 even for BIG_ENDIAN (blend.c seems to think so) ? */
143 /*****************************************************************************
144 * OpenScaler: probe the filter and return score
145 *****************************************************************************/
146 static int OpenScaler( vlc_object_t
*p_this
)
148 filter_t
*p_filter
= (filter_t
*)p_this
;
153 if( GetParameters( NULL
,
154 &p_filter
->fmt_in
.video
,
155 &p_filter
->fmt_out
.video
, 0 ) )
158 /* Allocate the memory needed to store the decoder's structure */
159 if( ( p_filter
->p_sys
= p_sys
= calloc(1, sizeof(filter_sys_t
)) ) == NULL
)
162 /* Set CPU capabilities */
163 p_sys
->i_cpu_mask
= GetSwsCpuMask();
166 i_sws_mode
= var_CreateGetInteger( p_filter
, "swscale-mode" );
169 case 0: p_sys
->i_sws_flags
= SWS_FAST_BILINEAR
; break;
170 case 1: p_sys
->i_sws_flags
= SWS_BILINEAR
; break;
171 case 2: p_sys
->i_sws_flags
= SWS_BICUBIC
; break;
172 case 3: p_sys
->i_sws_flags
= SWS_X
; break;
173 case 4: p_sys
->i_sws_flags
= SWS_POINT
; break;
174 case 5: p_sys
->i_sws_flags
= SWS_AREA
; break;
175 case 6: p_sys
->i_sws_flags
= SWS_BICUBLIN
; break;
176 case 7: p_sys
->i_sws_flags
= SWS_GAUSS
; break;
177 case 8: p_sys
->i_sws_flags
= SWS_SINC
; break;
178 case 9: p_sys
->i_sws_flags
= SWS_LANCZOS
; break;
179 case 10: p_sys
->i_sws_flags
= SWS_SPLINE
; break;
180 default: p_sys
->i_sws_flags
= SWS_BICUBIC
; i_sws_mode
= 2; break;
184 memset( &p_sys
->fmt_in
, 0, sizeof(p_sys
->fmt_in
) );
185 memset( &p_sys
->fmt_out
, 0, sizeof(p_sys
->fmt_out
) );
187 if( Init( p_filter
) )
189 if( p_sys
->p_filter
)
190 sws_freeFilter( p_sys
->p_filter
);
196 p_filter
->pf_video_filter
= Filter
;
198 msg_Dbg( p_filter
, "%ix%i (%ix%i) chroma: %4.4s -> %ix%i (%ix%i) chroma: %4.4s with scaling using %s",
199 p_filter
->fmt_in
.video
.i_visible_width
, p_filter
->fmt_in
.video
.i_visible_height
,
200 p_filter
->fmt_in
.video
.i_width
, p_filter
->fmt_in
.video
.i_height
,
201 (char *)&p_filter
->fmt_in
.video
.i_chroma
,
202 p_filter
->fmt_out
.video
.i_visible_width
, p_filter
->fmt_out
.video
.i_visible_height
,
203 p_filter
->fmt_out
.video
.i_width
, p_filter
->fmt_out
.video
.i_height
,
204 (char *)&p_filter
->fmt_out
.video
.i_chroma
,
205 ppsz_mode_descriptions
[i_sws_mode
] );
210 /*****************************************************************************
211 * CloseFilter: clean up the filter
212 *****************************************************************************/
213 static void CloseScaler( vlc_object_t
*p_this
)
215 filter_t
*p_filter
= (filter_t
*)p_this
;
216 filter_sys_t
*p_sys
= p_filter
->p_sys
;
219 if( p_sys
->p_filter
)
220 sws_freeFilter( p_sys
->p_filter
);
224 /*****************************************************************************
226 *****************************************************************************/
227 static int GetSwsCpuMask(void)
231 #if LIBSWSCALE_VERSION_MAJOR < 4
232 #if defined(__i386__) || defined(__x86_64__)
234 i_sws_cpu
|= SWS_CPU_CAPS_MMX
;
235 #if (LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0))
236 if( vlc_CPU_MMXEXT() )
237 i_sws_cpu
|= SWS_CPU_CAPS_MMX2
;
239 if( vlc_CPU_3dNOW() )
240 i_sws_cpu
|= SWS_CPU_CAPS_3DNOW
;
241 #elif defined(__ppc__) || defined(__ppc64__) || defined(__powerpc__)
242 if( vlc_CPU_ALTIVEC() )
243 i_sws_cpu
|= SWS_CPU_CAPS_ALTIVEC
;
250 static void FixParameters( int *pi_fmt
, bool *pb_has_a
, bool *pb_swap_uv
, vlc_fourcc_t fmt
)
254 case VLC_CODEC_YUV422A
:
255 *pi_fmt
= AV_PIX_FMT_YUV422P
;
258 case VLC_CODEC_YUV420A
:
259 *pi_fmt
= AV_PIX_FMT_YUV420P
;
263 *pi_fmt
= AV_PIX_FMT_YUV444P
;
267 *pi_fmt
= AV_PIX_FMT_BGR32
;
271 *pi_fmt
= AV_PIX_FMT_BGR32_1
;
275 *pi_fmt
= AV_PIX_FMT_RGB32
;
279 *pi_fmt
= AV_PIX_FMT_YUV420P
;
283 *pi_fmt
= AV_PIX_FMT_YUV410P
;
291 static int GetParameters( ScalerConfiguration
*p_cfg
,
292 const video_format_t
*p_fmti
,
293 const video_format_t
*p_fmto
,
294 int i_sws_flags_default
)
299 bool b_has_ai
= false;
300 bool b_has_ao
= false;
301 int i_sws_flags
= i_sws_flags_default
;
302 bool b_swap_uvi
= false;
303 bool b_swap_uvo
= false;
305 GetFfmpegChroma( &i_fmti
, p_fmti
);
306 GetFfmpegChroma( &i_fmto
, p_fmto
);
308 if( p_fmti
->i_chroma
== p_fmto
->i_chroma
)
310 if( p_fmti
->i_chroma
== VLC_CODEC_YUVP
&& ALLOW_YUVP
)
312 i_fmti
= i_fmto
= AV_PIX_FMT_GRAY8
;
313 i_sws_flags
= SWS_POINT
;
317 FixParameters( &i_fmti
, &b_has_ai
, &b_swap_uvi
, p_fmti
->i_chroma
);
318 FixParameters( &i_fmto
, &b_has_ao
, &b_swap_uvo
, p_fmto
->i_chroma
);
320 #if !defined (__ANDROID__) && !defined(TARGET_OS_IPHONE)
321 /* FIXME TODO removed when ffmpeg is fixed
322 * Without SWS_ACCURATE_RND the quality is really bad for some conversions */
325 case AV_PIX_FMT_ARGB
:
326 case AV_PIX_FMT_RGBA
:
327 case AV_PIX_FMT_ABGR
:
328 i_sws_flags
|= SWS_ACCURATE_RND
;
335 p_cfg
->i_fmti
= i_fmti
;
336 p_cfg
->i_fmto
= i_fmto
;
337 p_cfg
->b_has_a
= b_has_ai
&& b_has_ao
;
338 p_cfg
->b_add_a
= (!b_has_ai
) && b_has_ao
;
339 p_cfg
->b_copy
= i_fmti
== i_fmto
&&
340 p_fmti
->i_visible_width
== p_fmto
->i_visible_width
&&
341 p_fmti
->i_visible_height
== p_fmto
->i_visible_height
;
342 p_cfg
->b_swap_uvi
= b_swap_uvi
;
343 p_cfg
->b_swap_uvo
= b_swap_uvo
;
344 p_cfg
->i_sws_flags
= i_sws_flags
;
347 if( i_fmti
< 0 || i_fmto
< 0 )
353 static int Init( filter_t
*p_filter
)
355 filter_sys_t
*p_sys
= p_filter
->p_sys
;
356 const video_format_t
*p_fmti
= &p_filter
->fmt_in
.video
;
357 video_format_t
*p_fmto
= &p_filter
->fmt_out
.video
;
359 if( p_fmti
->orientation
!= p_fmto
->orientation
)
362 if( video_format_IsSimilar( p_fmti
, &p_sys
->fmt_in
) &&
363 video_format_IsSimilar( p_fmto
, &p_sys
->fmt_out
) &&
371 /* Init with new parameters */
372 ScalerConfiguration cfg
;
373 if( GetParameters( &cfg
, p_fmti
, p_fmto
, p_sys
->i_sws_flags
) )
375 msg_Err( p_filter
, "format not supported" );
378 if( p_fmti
->i_visible_width
== 0 || p_fmti
->i_visible_height
== 0 ||
379 p_fmto
->i_visible_width
== 0 || p_fmto
->i_visible_height
== 0 )
381 msg_Err( p_filter
, "invalid scaling: %ix%i -> %ix%i",
382 p_fmti
->i_visible_width
, p_fmti
->i_visible_height
,
383 p_fmto
->i_visible_width
, p_fmto
->i_visible_height
);
387 p_sys
->desc_in
= vlc_fourcc_GetChromaDescription( p_fmti
->i_chroma
);
388 p_sys
->desc_out
= vlc_fourcc_GetChromaDescription( p_fmto
->i_chroma
);
389 if( p_sys
->desc_in
== NULL
|| p_sys
->desc_out
== NULL
)
392 /* swscale does not like too small width */
393 p_sys
->i_extend_factor
= 1;
394 while( __MIN( p_fmti
->i_visible_width
, p_fmto
->i_visible_width
) * p_sys
->i_extend_factor
< MINIMUM_WIDTH
)
395 p_sys
->i_extend_factor
++;
397 const unsigned i_fmti_visible_width
= p_fmti
->i_visible_width
* p_sys
->i_extend_factor
;
398 const unsigned i_fmto_visible_width
= p_fmto
->i_visible_width
* p_sys
->i_extend_factor
;
399 for( int n
= 0; n
< (cfg
.b_has_a
? 2 : 1); n
++ )
401 const int i_fmti
= n
== 0 ? cfg
.i_fmti
: AV_PIX_FMT_GRAY8
;
402 const int i_fmto
= n
== 0 ? cfg
.i_fmto
: AV_PIX_FMT_GRAY8
;
403 struct SwsContext
*ctx
;
405 ctx
= sws_getContext( i_fmti_visible_width
, p_fmti
->i_visible_height
, i_fmti
,
406 i_fmto_visible_width
, p_fmto
->i_visible_height
, i_fmto
,
407 cfg
.i_sws_flags
| p_sys
->i_cpu_mask
,
408 p_sys
->p_filter
, NULL
, 0 );
416 p_sys
->p_src_a
= picture_New( VLC_CODEC_GREY
, i_fmti_visible_width
, p_fmti
->i_visible_height
, 0, 1 );
417 p_sys
->p_dst_a
= picture_New( VLC_CODEC_GREY
, i_fmto_visible_width
, p_fmto
->i_visible_height
, 0, 1 );
419 if( p_sys
->i_extend_factor
!= 1 )
421 p_sys
->p_src_e
= picture_New( p_fmti
->i_chroma
, i_fmti_visible_width
, p_fmti
->i_visible_height
, 0, 1 );
422 p_sys
->p_dst_e
= picture_New( p_fmto
->i_chroma
, i_fmto_visible_width
, p_fmto
->i_visible_height
, 0, 1 );
425 memset( p_sys
->p_src_e
->p
[0].p_pixels
, 0, p_sys
->p_src_e
->p
[0].i_pitch
* p_sys
->p_src_e
->p
[0].i_lines
);
427 memset( p_sys
->p_dst_e
->p
[0].p_pixels
, 0, p_sys
->p_dst_e
->p
[0].i_pitch
* p_sys
->p_dst_e
->p
[0].i_lines
);
431 ( cfg
.b_has_a
&& ( !p_sys
->ctxA
|| !p_sys
->p_src_a
|| !p_sys
->p_dst_a
) ) ||
432 ( p_sys
->i_extend_factor
!= 1 && ( !p_sys
->p_src_e
|| !p_sys
->p_dst_e
) ) )
434 msg_Err( p_filter
, "could not init SwScaler and/or allocate memory" );
439 if (p_filter
->b_allow_fmt_out_change
)
442 * If the transformation is not homothetic we must modify the
443 * aspect ratio of the output format in order to have the
444 * output picture displayed correctly and not stretched
445 * horizontally or vertically.
446 * WARNING: this is a hack, ideally this should not be needed
447 * and the vout should update its video format instead.
449 unsigned i_sar_num
= p_fmti
->i_sar_num
* p_fmti
->i_visible_width
;
450 unsigned i_sar_den
= p_fmti
->i_sar_den
* p_fmto
->i_visible_width
;
451 vlc_ureduce(&i_sar_num
, &i_sar_den
, i_sar_num
, i_sar_den
, 65536);
452 i_sar_num
*= p_fmto
->i_visible_height
;
453 i_sar_den
*= p_fmti
->i_visible_height
;
454 vlc_ureduce(&i_sar_num
, &i_sar_den
, i_sar_num
, i_sar_den
, 65536);
455 p_fmto
->i_sar_num
= i_sar_num
;
456 p_fmto
->i_sar_den
= i_sar_den
;
459 p_sys
->b_add_a
= cfg
.b_add_a
;
460 p_sys
->b_copy
= cfg
.b_copy
;
461 p_sys
->fmt_in
= *p_fmti
;
462 p_sys
->fmt_out
= *p_fmto
;
463 p_sys
->b_swap_uvi
= cfg
.b_swap_uvi
;
464 p_sys
->b_swap_uvo
= cfg
.b_swap_uvo
;
469 static void Clean( filter_t
*p_filter
)
471 filter_sys_t
*p_sys
= p_filter
->p_sys
;
474 picture_Release( p_sys
->p_src_e
);
476 picture_Release( p_sys
->p_dst_e
);
479 picture_Release( p_sys
->p_src_a
);
481 picture_Release( p_sys
->p_dst_a
);
484 sws_freeContext( p_sys
->ctxA
);
487 sws_freeContext( p_sys
->ctx
);
489 /* We have to set it to null has we call be called again :( */
492 p_sys
->p_src_a
= NULL
;
493 p_sys
->p_dst_a
= NULL
;
494 p_sys
->p_src_e
= NULL
;
495 p_sys
->p_dst_e
= NULL
;
498 static void GetPixels( uint8_t *pp_pixel
[4], int pi_pitch
[4],
499 const vlc_chroma_description_t
*desc
,
500 const video_format_t
*fmt
,
501 const picture_t
*p_picture
, unsigned planes
,
506 if( planes
> (unsigned)p_picture
->i_planes
)
507 planes
= p_picture
->i_planes
;
508 assert( !b_swap_uv
|| planes
>= 3 );
510 for( ; i
< planes
; i
++ )
512 const plane_t
*p
= p_picture
->p
+ i
;
513 if( b_swap_uv
&& (i
== 1 || i
== 2) )
514 p
= p_picture
->p
+ 3 - i
;
516 pp_pixel
[i
] = p
->p_pixels
517 + (((fmt
->i_x_offset
* desc
->p
[i
].w
.num
) / desc
->p
[i
].w
.den
)
519 + (((fmt
->i_y_offset
* desc
->p
[i
].h
.num
) / desc
->p
[i
].h
.den
)
521 pi_pitch
[i
] = p
->i_pitch
;
531 static void ExtractA( picture_t
*p_dst
, const picture_t
*restrict p_src
,
534 plane_t
*d
= &p_dst
->p
[0];
535 const plane_t
*s
= &p_src
->p
[0];
537 for( unsigned y
= 0; y
< p_dst
->format
.i_height
; y
++ )
538 for( unsigned x
= 0; x
< p_dst
->format
.i_width
; x
++ )
539 d
->p_pixels
[y
*d
->i_pitch
+x
] = s
->p_pixels
[y
*s
->i_pitch
+4*x
+offset
];
542 static void InjectA( picture_t
*p_dst
, const picture_t
*restrict p_src
,
545 plane_t
*d
= &p_dst
->p
[0];
546 const plane_t
*s
= &p_src
->p
[0];
548 for( unsigned y
= 0; y
< p_src
->format
.i_height
; y
++ )
549 for( unsigned x
= 0; x
< p_src
->format
.i_width
; x
++ )
550 d
->p_pixels
[y
*d
->i_pitch
+4*x
+offset
] = s
->p_pixels
[y
*s
->i_pitch
+x
];
553 static void FillA( plane_t
*d
, unsigned i_offset
)
555 for( int y
= 0; y
< d
->i_visible_lines
; y
++ )
556 for( int x
= 0; x
< d
->i_visible_pitch
; x
+= d
->i_pixel_pitch
)
557 d
->p_pixels
[y
*d
->i_pitch
+x
+i_offset
] = 0xff;
560 static void CopyPad( picture_t
*p_dst
, const picture_t
*p_src
)
562 picture_Copy( p_dst
, p_src
);
563 for( int n
= 0; n
< p_dst
->i_planes
; n
++ )
565 const plane_t
*s
= &p_src
->p
[n
];
566 plane_t
*d
= &p_dst
->p
[n
];
568 for( int y
= 0; y
< s
->i_lines
&& y
< d
->i_lines
; y
++ )
570 for( int x
= s
->i_visible_pitch
; x
< d
->i_visible_pitch
; x
+= s
->i_pixel_pitch
)
571 memcpy( &d
->p_pixels
[y
*d
->i_pitch
+ x
], &d
->p_pixels
[y
*d
->i_pitch
+ s
->i_visible_pitch
- s
->i_pixel_pitch
], s
->i_pixel_pitch
);
576 static void SwapUV( picture_t
*p_dst
, const picture_t
*p_src
)
578 picture_t tmp
= *p_src
;
579 tmp
.p
[1] = p_src
->p
[2];
580 tmp
.p
[2] = p_src
->p
[1];
582 picture_CopyPixels( p_dst
, &tmp
);
585 static void Convert( filter_t
*p_filter
, struct SwsContext
*ctx
,
586 picture_t
*p_dst
, picture_t
*p_src
, int i_height
,
587 int i_plane_count
, bool b_swap_uvi
, bool b_swap_uvo
)
589 filter_sys_t
*p_sys
= p_filter
->p_sys
;
590 uint8_t palette
[AVPALETTE_SIZE
];
591 uint8_t *src
[4]; int src_stride
[4];
592 uint8_t *dst
[4]; int dst_stride
[4];
594 GetPixels( src
, src_stride
, p_sys
->desc_in
, &p_filter
->fmt_in
.video
,
595 p_src
, i_plane_count
, b_swap_uvi
);
596 if( p_filter
->fmt_in
.video
.i_chroma
== VLC_CODEC_RGBP
)
598 memset( palette
, 0, sizeof(palette
) );
599 if( p_filter
->fmt_in
.video
.p_palette
)
600 memcpy( palette
, p_filter
->fmt_in
.video
.p_palette
->palette
,
601 __MIN( sizeof(video_palette_t
), AVPALETTE_SIZE
) );
606 GetPixels( dst
, dst_stride
, p_sys
->desc_out
, &p_filter
->fmt_out
.video
,
607 p_dst
, i_plane_count
, b_swap_uvo
);
609 #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)
610 sws_scale( ctx
, src
, src_stride
, 0, i_height
,
613 sws_scale_ordered( ctx
, src
, src_stride
, 0, i_height
,
618 /****************************************************************************
619 * Filter: the whole thing
620 ****************************************************************************
621 * This function is called just after the thread is launched.
622 ****************************************************************************/
623 static picture_t
*Filter( filter_t
*p_filter
, picture_t
*p_pic
)
625 filter_sys_t
*p_sys
= p_filter
->p_sys
;
626 const video_format_t
*p_fmti
= &p_filter
->fmt_in
.video
;
627 const video_format_t
*p_fmto
= &p_filter
->fmt_out
.video
;
628 picture_t
*p_pic_dst
;
630 /* Check if format properties changed */
631 if( Init( p_filter
) )
633 picture_Release( p_pic
);
637 /* Request output picture */
638 p_pic_dst
= filter_NewPicture( p_filter
);
641 picture_Release( p_pic
);
646 picture_t
*p_src
= p_pic
;
647 picture_t
*p_dst
= p_pic_dst
;
648 if( p_sys
->i_extend_factor
!= 1 )
650 p_src
= p_sys
->p_src_e
;
651 p_dst
= p_sys
->p_dst_e
;
653 CopyPad( p_src
, p_pic
);
656 if( p_sys
->b_copy
&& p_sys
->b_swap_uvi
== p_sys
->b_swap_uvo
)
657 picture_CopyPixels( p_dst
, p_src
);
658 else if( p_sys
->b_copy
)
659 SwapUV( p_dst
, p_src
);
662 /* Even if alpha is unused, swscale expects the pointer to be set */
663 const int n_planes
= !p_sys
->ctxA
&& (p_src
->i_planes
== 4 ||
664 p_dst
->i_planes
== 4) ? 4 : 3;
665 Convert( p_filter
, p_sys
->ctx
, p_dst
, p_src
, p_fmti
->i_visible_height
,
666 n_planes
, p_sys
->b_swap_uvi
, p_sys
->b_swap_uvo
);
670 /* We extract the A plane to rescale it, and then we reinject it. */
671 if( p_fmti
->i_chroma
== VLC_CODEC_RGBA
|| p_fmti
->i_chroma
== VLC_CODEC_BGRA
)
672 ExtractA( p_sys
->p_src_a
, p_src
, OFFSET_A
);
673 else if( p_fmti
->i_chroma
== VLC_CODEC_ARGB
)
674 ExtractA( p_sys
->p_src_a
, p_src
, 0 );
676 plane_CopyPixels( p_sys
->p_src_a
->p
, p_src
->p
+A_PLANE
);
678 Convert( p_filter
, p_sys
->ctxA
, p_sys
->p_dst_a
, p_sys
->p_src_a
,
679 p_fmti
->i_visible_height
, 1, false, false );
680 if( p_fmto
->i_chroma
== VLC_CODEC_RGBA
|| p_fmto
->i_chroma
== VLC_CODEC_BGRA
)
681 InjectA( p_dst
, p_sys
->p_dst_a
, OFFSET_A
);
682 else if( p_fmto
->i_chroma
== VLC_CODEC_ARGB
)
683 InjectA( p_dst
, p_sys
->p_dst_a
, 0 );
685 plane_CopyPixels( p_dst
->p
+A_PLANE
, p_sys
->p_dst_a
->p
);
687 else if( p_sys
->b_add_a
)
689 /* We inject a complete opaque alpha plane */
690 if( p_fmto
->i_chroma
== VLC_CODEC_RGBA
|| p_fmto
->i_chroma
== VLC_CODEC_BGRA
)
691 FillA( &p_dst
->p
[0], OFFSET_A
);
692 else if( p_fmto
->i_chroma
== VLC_CODEC_ARGB
)
693 FillA( &p_dst
->p
[0], 0 );
695 FillA( &p_dst
->p
[A_PLANE
], 0 );
698 if( p_sys
->i_extend_factor
!= 1 )
700 picture_CopyPixels( p_pic_dst
, p_dst
);
703 picture_CopyProperties( p_pic_dst
, p_pic
);
704 picture_Release( p_pic
);
708 #else /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */
710 int OpenScaler( vlc_object_t
*p_this
)
715 void CloseScaler( vlc_object_t
*p_this
)
719 #endif /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */