| | 78 | |
|---|
| | 79 | /* Version checking */ |
|---|
| | 80 | #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) |
|---|
| | 81 | /***************************************************************************** |
|---|
| | 82 | * filter_sys_t : filter descriptor |
|---|
| | 83 | *****************************************************************************/ |
|---|
| | 84 | struct filter_sys_t |
|---|
| | 85 | { |
|---|
| | 86 | struct SwsContext *ctx; |
|---|
| | 87 | SwsFilter *p_src_filter; |
|---|
| | 88 | SwsFilter *p_dst_filter; |
|---|
| | 89 | int i_cpu_mask, i_sws_flags; |
|---|
| | 90 | |
|---|
| | 91 | es_format_t fmt_in; |
|---|
| | 92 | es_format_t fmt_out; |
|---|
| | 93 | }; |
|---|
| | 94 | |
|---|
| | 95 | /***************************************************************************** |
|---|
| | 96 | * OpenScaler: probe the filter and return score |
|---|
| | 97 | *****************************************************************************/ |
|---|
| | 98 | static int OpenScaler( vlc_object_t *p_this ) |
|---|
| | 99 | { |
|---|
| | 100 | filter_t *p_filter = (filter_t*)p_this; |
|---|
| | 101 | filter_sys_t *p_sys; |
|---|
| | 102 | vlc_value_t val; |
|---|
| | 103 | |
|---|
| | 104 | int i_fmt_in, i_fmt_out; |
|---|
| | 105 | unsigned int i_cpu; |
|---|
| | 106 | int i_sws_mode; |
|---|
| | 107 | |
|---|
| | 108 | float sws_lum_gblur = 0.0, sws_chr_gblur = 0.0; |
|---|
| | 109 | int sws_chr_vshift = 0, sws_chr_hshift = 0; |
|---|
| | 110 | float sws_chr_sharpen = 0.0, sws_lum_sharpen = 0.0; |
|---|
| | 111 | |
|---|
| | 112 | /* Supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR24, |
|---|
| | 113 | * BGR16, BGR15, RGB32, RGB24, Y8/Y800, YVU9/IF09 */ |
|---|
| | 114 | i_fmt_in = GetFfmpegChroma(p_filter->fmt_in.video.i_chroma); |
|---|
| | 115 | /* Supported output formats: YV12, I420/IYUV, YUY2, UYVY, |
|---|
| | 116 | * {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09 */ |
|---|
| | 117 | i_fmt_out = GetFfmpegChroma(p_filter->fmt_out.video.i_chroma); |
|---|
| | 118 | if( ( i_fmt_in < 0 ) || ( i_fmt_out < 0 ) ) |
|---|
| | 119 | { |
|---|
| | 120 | return VLC_EGENERIC; |
|---|
| | 121 | } |
|---|
| | 122 | |
|---|
| | 123 | /* Allocate the memory needed to store the decoder's structure */ |
|---|
| | 124 | if( ( p_filter->p_sys = p_sys = |
|---|
| | 125 | (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL ) |
|---|
| | 126 | { |
|---|
| | 127 | return VLC_ENOMEM; |
|---|
| | 128 | } |
|---|
| | 129 | |
|---|
| | 130 | swscale_fast_memcpy = vlc_memcpy; |
|---|
| | 131 | |
|---|
| | 132 | /* Set CPU capabilities */ |
|---|
| | 133 | i_cpu = vlc_CPU(); |
|---|
| | 134 | p_sys->i_cpu_mask = 0; |
|---|
| | 135 | if( i_cpu & CPU_CAPABILITY_MMX ) |
|---|
| | 136 | { |
|---|
| | 137 | p_sys->i_cpu_mask |= SWS_CPU_CAPS_MMX; |
|---|
| | 138 | } |
|---|
| | 139 | #if (LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0)) |
|---|
| | 140 | if( i_cpu & CPU_CAPABILITY_MMXEXT ) |
|---|
| | 141 | { |
|---|
| | 142 | p_sys->i_cpu_mask |= SWS_CPU_CAPS_MMX2; |
|---|
| | 143 | } |
|---|
| | 144 | #endif |
|---|
| | 145 | if( i_cpu & CPU_CAPABILITY_3DNOW ) |
|---|
| | 146 | { |
|---|
| | 147 | p_sys->i_cpu_mask |= SWS_CPU_CAPS_3DNOW; |
|---|
| | 148 | } |
|---|
| | 149 | if( i_cpu & CPU_CAPABILITY_ALTIVEC ) |
|---|
| | 150 | { |
|---|
| | 151 | p_sys->i_cpu_mask |= SWS_CPU_CAPS_ALTIVEC; |
|---|
| | 152 | } |
|---|
| | 153 | |
|---|
| | 154 | var_Create( p_filter, "swscale-mode", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT ); |
|---|
| | 155 | var_Get( p_filter, "swscale-mode", &val ); |
|---|
| | 156 | i_sws_mode = val.i_int; |
|---|
| | 157 | |
|---|
| | 158 | switch( i_sws_mode ) |
|---|
| | 159 | { |
|---|
| | 160 | case 0: p_sys->i_sws_flags = SWS_FAST_BILINEAR; break; |
|---|
| | 161 | case 1: p_sys->i_sws_flags = SWS_BILINEAR; break; |
|---|
| | 162 | case 2: p_sys->i_sws_flags = SWS_BICUBIC; break; |
|---|
| | 163 | case 3: p_sys->i_sws_flags = SWS_X; break; |
|---|
| | 164 | case 4: p_sys->i_sws_flags = SWS_POINT; break; |
|---|
| | 165 | case 5: p_sys->i_sws_flags = SWS_AREA; break; |
|---|
| | 166 | case 6: p_sys->i_sws_flags = SWS_BICUBLIN; break; |
|---|
| | 167 | case 7: p_sys->i_sws_flags = SWS_GAUSS; break; |
|---|
| | 168 | case 8: p_sys->i_sws_flags = SWS_SINC; break; |
|---|
| | 169 | case 9: p_sys->i_sws_flags = SWS_LANCZOS; break; |
|---|
| | 170 | case 10: p_sys->i_sws_flags = SWS_SPLINE; break; |
|---|
| | 171 | default: p_sys->i_sws_flags = SWS_FAST_BILINEAR; i_sws_mode = 0; break; |
|---|
| | 172 | } |
|---|
| | 173 | |
|---|
| | 174 | p_sys->p_src_filter = NULL; |
|---|
| | 175 | p_sys->p_dst_filter = NULL; |
|---|
| | 176 | p_sys->p_src_filter = |
|---|
| | 177 | sws_getDefaultFilter( sws_lum_gblur, sws_chr_gblur, |
|---|
| | 178 | sws_lum_sharpen, sws_chr_sharpen, |
|---|
| | 179 | sws_chr_hshift, sws_chr_vshift, 0 ); |
|---|
| | 180 | |
|---|
| | 181 | /* Misc init */ |
|---|
| | 182 | p_sys->ctx = NULL; |
|---|
| | 183 | p_filter->pf_video_filter = Filter; |
|---|
| | 184 | es_format_Init( &p_sys->fmt_in, 0, 0 ); |
|---|
| | 185 | es_format_Init( &p_sys->fmt_out, 0, 0 ); |
|---|
| | 186 | |
|---|
| | 187 | if( CheckInit( p_filter ) != VLC_SUCCESS ) |
|---|
| | 188 | { |
|---|
| | 189 | if( p_sys->p_src_filter ) sws_freeFilter( p_sys->p_src_filter ); |
|---|
| | 190 | free( p_sys ); |
|---|
| | 191 | return VLC_EGENERIC; |
|---|
| | 192 | } |
|---|
| | 193 | |
|---|
| | 194 | msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s", |
|---|
| | 195 | p_filter->fmt_in.video.i_width, p_filter->fmt_in.video.i_height, |
|---|
| | 196 | (char *)&p_filter->fmt_in.video.i_chroma, |
|---|
| | 197 | p_filter->fmt_out.video.i_width, p_filter->fmt_out.video.i_height, |
|---|
| | 198 | (char *)&p_filter->fmt_out.video.i_chroma ); |
|---|
| | 199 | |
|---|
| | 200 | if( p_filter->fmt_in.video.i_width != p_filter->fmt_out.video.i_width || |
|---|
| | 201 | p_filter->fmt_in.video.i_height != p_filter->fmt_out.video.i_height ) |
|---|
| | 202 | { |
|---|
| | 203 | msg_Dbg( p_filter, "scaling mode: %s", |
|---|
| | 204 | ppsz_mode_descriptions[i_sws_mode] ); |
|---|
| | 205 | } |
|---|
| | 206 | |
|---|
| | 207 | return VLC_SUCCESS; |
|---|
| | 208 | } |
|---|
| | 209 | |
|---|
| | 210 | /***************************************************************************** |
|---|
| | 211 | * CloseFilter: clean up the filter |
|---|
| | 212 | *****************************************************************************/ |
|---|
| | 213 | static void CloseScaler( vlc_object_t *p_this ) |
|---|
| | 214 | { |
|---|
| | 215 | filter_t *p_filter = (filter_t*)p_this; |
|---|
| | 216 | filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| | 217 | |
|---|
| | 218 | if( p_sys->ctx ) sws_freeContext( p_sys->ctx ); |
|---|
| | 219 | if( p_sys->p_src_filter ) sws_freeFilter( p_sys->p_src_filter ); |
|---|
| | 220 | free( p_sys ); |
|---|
| | 221 | } |
|---|
| | 222 | |
|---|
| | 223 | /***************************************************************************** |
|---|
| | 224 | * CheckInit: Initialise filter when necessary |
|---|
| | 225 | *****************************************************************************/ |
|---|
| | 226 | static int CheckInit( filter_t *p_filter ) |
|---|
| | 227 | { |
|---|
| | 228 | filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| | 229 | |
|---|
| | 230 | if( ( p_filter->fmt_in.video.i_width != p_sys->fmt_in.video.i_width ) || |
|---|
| | 231 | ( p_filter->fmt_in.video.i_height != p_sys->fmt_in.video.i_height ) || |
|---|
| | 232 | ( p_filter->fmt_out.video.i_width != p_sys->fmt_out.video.i_width ) || |
|---|
| | 233 | ( p_filter->fmt_out.video.i_height != p_sys->fmt_out.video.i_height ) ) |
|---|
| | 234 | { |
|---|
| | 235 | int i_fmt_in, i_fmt_out; |
|---|
| | 236 | |
|---|
| | 237 | i_fmt_in = GetFfmpegChroma(p_filter->fmt_in.video.i_chroma); |
|---|
| | 238 | i_fmt_out = GetFfmpegChroma(p_filter->fmt_out.video.i_chroma); |
|---|
| | 239 | if( (i_fmt_in < 0) || (i_fmt_out < 0) ) |
|---|
| | 240 | { |
|---|
| | 241 | msg_Err( p_filter, "format not supported" ); |
|---|
| | 242 | return VLC_EGENERIC; |
|---|
| | 243 | } |
|---|
| | 244 | |
|---|
| | 245 | if( p_sys->ctx ) sws_freeContext( p_sys->ctx ); |
|---|
| | 246 | |
|---|
| | 247 | p_sys->ctx = |
|---|
| | 248 | sws_getContext( p_filter->fmt_in.video.i_width, |
|---|
| | 249 | p_filter->fmt_in.video.i_height, i_fmt_in, |
|---|
| | 250 | p_filter->fmt_out.video.i_width, |
|---|
| | 251 | p_filter->fmt_out.video.i_height, i_fmt_out, |
|---|
| | 252 | p_sys->i_sws_flags | p_sys->i_cpu_mask, |
|---|
| | 253 | p_sys->p_src_filter, p_sys->p_dst_filter, 0 ); |
|---|
| | 254 | if( !p_sys->ctx ) |
|---|
| | 255 | { |
|---|
| | 256 | msg_Err( p_filter, "could not init SwScaler" ); |
|---|
| | 257 | return VLC_EGENERIC; |
|---|
| | 258 | } |
|---|
| | 259 | |
|---|
| | 260 | p_sys->fmt_in = p_filter->fmt_in; |
|---|
| | 261 | p_sys->fmt_out = p_filter->fmt_out; |
|---|
| | 262 | } |
|---|
| | 263 | |
|---|
| | 264 | return VLC_SUCCESS; |
|---|
| | 265 | } |
|---|
| | 266 | |
|---|
| | 267 | /**************************************************************************** |
|---|
| | 268 | * Filter: the whole thing |
|---|
| | 269 | **************************************************************************** |
|---|
| | 270 | * This function is called just after the thread is launched. |
|---|
| | 271 | ****************************************************************************/ |
|---|
| | 272 | static picture_t *Filter( filter_t *p_filter, picture_t *p_pic ) |
|---|
| | 273 | { |
|---|
| | 274 | filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| | 275 | uint8_t *src[3]; int src_stride[3]; |
|---|
| | 276 | uint8_t *dst[3]; int dst_stride[3]; |
|---|
| | 277 | picture_t *p_pic_dst; |
|---|
| | 278 | int i_plane; |
|---|
| | 279 | int i_nb_planes = p_pic->i_planes; |
|---|
| | 280 | |
|---|
| | 281 | /* Check if format properties changed */ |
|---|
| | 282 | if( CheckInit( p_filter ) != VLC_SUCCESS ) return NULL; |
|---|
| | 283 | |
|---|
| | 284 | /* Request output picture */ |
|---|
| | 285 | p_pic_dst = p_filter->pf_vout_buffer_new( p_filter ); |
|---|
| | 286 | if( !p_pic_dst ) |
|---|
| | 287 | { |
|---|
| | 288 | msg_Warn( p_filter, "can't get output picture" ); |
|---|
| | 289 | return NULL; |
|---|
| | 290 | } |
|---|
| | 291 | |
|---|
| | 292 | if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','V','A') ) |
|---|
| | 293 | { |
|---|
| | 294 | i_nb_planes = 3; |
|---|
| | 295 | memset( p_pic_dst->p[3].p_pixels, 0xff, p_filter->fmt_out.video.i_height |
|---|
| | 296 | * p_pic_dst->p[3].i_pitch ); |
|---|
| | 297 | } |
|---|
| | 298 | |
|---|
| | 299 | for( i_plane = 0; i_plane < __MIN(3, p_pic->i_planes); i_plane++ ) |
|---|
| | 300 | { |
|---|
| | 301 | src[i_plane] = p_pic->p[i_plane].p_pixels; |
|---|
| | 302 | src_stride[i_plane] = p_pic->p[i_plane].i_pitch; |
|---|
| | 303 | } |
|---|
| | 304 | for( i_plane = 0; i_plane < __MIN(3, i_nb_planes); i_plane++ ) |
|---|
| | 305 | { |
|---|
| | 306 | dst[i_plane] = p_pic_dst->p[i_plane].p_pixels; |
|---|
| | 307 | dst_stride[i_plane] = p_pic_dst->p[i_plane].i_pitch; |
|---|
| | 308 | } |
|---|
| | 309 | |
|---|
| | 310 | #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) |
|---|
| | 311 | sws_scale( p_sys->ctx, src, src_stride, |
|---|
| | 312 | 0, p_filter->fmt_in.video.i_height, |
|---|
| | 313 | dst, dst_stride ); |
|---|
| | 314 | #else |
|---|
| | 315 | sws_scale_ordered( p_sys->ctx, src, src_stride, |
|---|
| | 316 | 0, p_filter->fmt_in.video.i_height, |
|---|
| | 317 | dst, dst_stride ); |
|---|
| | 318 | #endif |
|---|
| | 319 | |
|---|
| | 320 | p_pic_dst->date = p_pic->date; |
|---|
| | 321 | p_pic_dst->b_force = p_pic->b_force; |
|---|
| | 322 | p_pic_dst->i_nb_fields = p_pic->i_nb_fields; |
|---|
| | 323 | p_pic_dst->b_progressive = p_pic->b_progressive; |
|---|
| | 324 | p_pic_dst->b_top_field_first = p_pic->b_top_field_first; |
|---|
| | 325 | |
|---|
| | 326 | if( p_pic->pf_release ) |
|---|
| | 327 | p_pic->pf_release( p_pic ); |
|---|
| | 328 | return p_pic_dst; |
|---|
| | 329 | } |
|---|
| | 330 | |
|---|
| | 331 | #else /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */ |
|---|
| | 332 | |
|---|
| | 333 | int OpenScaler( vlc_object_t *p_this ) |
|---|
| | 334 | { |
|---|
| | 335 | return VLC_EGENERIC; |
|---|
| | 336 | } |
|---|
| | 337 | |
|---|
| | 338 | void CloseScaler( vlc_object_t *p_this ) |
|---|
| | 339 | { |
|---|
| | 340 | } |
|---|
| | 341 | |
|---|
| | 342 | #endif /* LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) */ |
|---|