Changeset 496977e364ae28fdb497fd370b1b42f988cbb076
- Timestamp:
- 28/07/08 00:03:52
(4 months ago)
- Author:
- Laurent Aimar <fenrir@videolan.org>
- git-committer:
- Laurent Aimar <fenrir@videolan.org> 1217196232 +0200
- git-parent:
[84387c930d3fb4eca3d4e319809fb511da9b18ef]
- git-author:
- Laurent Aimar <fenrir@videolan.org> 1217196164 +0200
- Message:
Workaround a limitation of swscaler that does not like too small width.
(It begins to have a lots of "workarounds" :(
-
Files:
-
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
| rbf6e5c3 |
r496977e |
|
| 94 | 94 | picture_t *p_src_a; |
|---|
| 95 | 95 | picture_t *p_dst_a; |
|---|
| | 96 | int i_extend_factor; |
|---|
| | 97 | picture_t *p_src_e; |
|---|
| | 98 | picture_t *p_dst_e; |
|---|
| 96 | 99 | }; |
|---|
| 97 | 100 | |
|---|
| … | … | |
| 107 | 110 | static int GetSwsCpuMask(void); |
|---|
| 108 | 111 | |
|---|
| 109 | | /* FFmpeg point resize quality seems really bad, let our scale module do it |
|---|
| | 112 | /* SwScaler point resize quality seems really bad, let our scale module do it |
|---|
| 110 | 113 | * (change it to true to try) */ |
|---|
| 111 | 114 | #define ALLOW_YUVP (false) |
|---|
| | 115 | /* SwScaler does not like too small picture */ |
|---|
| | 116 | #define MINIMUM_WIDTH (16) |
|---|
| 112 | 117 | |
|---|
| 113 | 118 | /***************************************************************************** |
|---|
| … | … | |
| 173 | 178 | p_sys->p_src_a = NULL; |
|---|
| 174 | 179 | p_sys->p_dst_a = NULL; |
|---|
| | 180 | p_sys->p_src_e = NULL; |
|---|
| | 181 | p_sys->p_dst_e = NULL; |
|---|
| 175 | 182 | memset( &p_sys->fmt_in, 0, sizeof(p_sys->fmt_in) ); |
|---|
| 176 | 183 | memset( &p_sys->fmt_out, 0, sizeof(p_sys->fmt_out) ); |
|---|
| … | … | |
| 311 | 318 | return VLC_EGENERIC; |
|---|
| 312 | 319 | } |
|---|
| 313 | | |
|---|
| | 320 | if( p_fmti->i_width <= 0 || p_fmto->i_width <= 0 ) |
|---|
| | 321 | { |
|---|
| | 322 | msg_Err( p_filter, "0 width not supported" ); |
|---|
| | 323 | return VLC_EGENERIC; |
|---|
| | 324 | } |
|---|
| | 325 | |
|---|
| | 326 | /* swscale does not like too small width */ |
|---|
| | 327 | p_sys->i_extend_factor = 1; |
|---|
| | 328 | while( __MIN( p_fmti->i_width, p_fmto->i_width ) * p_sys->i_extend_factor < MINIMUM_WIDTH) |
|---|
| | 329 | p_sys->i_extend_factor++; |
|---|
| | 330 | |
|---|
| | 331 | const unsigned i_fmti_width = p_fmti->i_width * p_sys->i_extend_factor; |
|---|
| | 332 | const unsigned i_fmto_width = p_fmto->i_width * p_sys->i_extend_factor; |
|---|
| 314 | 333 | for( int n = 0; n < (b_has_a ? 2 : 1); n++ ) |
|---|
| 315 | 334 | { |
|---|
| … | … | |
| 318 | 337 | struct SwsContext *ctx; |
|---|
| 319 | 338 | |
|---|
| 320 | | ctx = sws_getContext( p_fmti->i_width, p_fmti->i_height, i_fmti, |
|---|
| 321 | | p_fmto->i_width, p_fmto->i_height, i_fmto, |
|---|
| | 339 | ctx = sws_getContext( i_fmti_width, p_fmti->i_height, i_fmti, |
|---|
| | 340 | i_fmto_width, p_fmto->i_height, i_fmto, |
|---|
| 322 | 341 | i_sws_flags | p_sys->i_cpu_mask, |
|---|
| 323 | 342 | p_sys->p_src_filter, p_sys->p_dst_filter, 0 ); |
|---|
| … | … | |
| 329 | 348 | if( p_sys->ctxA ) |
|---|
| 330 | 349 | { |
|---|
| 331 | | p_sys->p_src_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), p_fmti->i_width, p_fmti->i_height, 0 ); |
|---|
| 332 | | p_sys->p_dst_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), p_fmto->i_width, p_fmto->i_height, 0 ); |
|---|
| | 350 | p_sys->p_src_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), i_fmti_width, p_fmti->i_height, 0 ); |
|---|
| | 351 | p_sys->p_dst_a = picture_New( VLC_FOURCC( 'G', 'R', 'E', 'Y' ), i_fmto_width, p_fmto->i_height, 0 ); |
|---|
| | 352 | } |
|---|
| | 353 | if( p_sys->i_extend_factor != 1 ) |
|---|
| | 354 | { |
|---|
| | 355 | p_sys->p_src_e = picture_New( p_fmti->i_chroma, i_fmti_width, p_fmti->i_height, 0 ); |
|---|
| | 356 | p_sys->p_dst_e = picture_New( p_fmto->i_chroma, i_fmto_width, p_fmto->i_height, 0 ); |
|---|
| | 357 | |
|---|
| | 358 | 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 ); |
|---|
| | 359 | 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 ); |
|---|
| 333 | 360 | } |
|---|
| 334 | 361 | |
|---|
| 335 | 362 | if( !p_sys->ctx || |
|---|
| 336 | | ( b_has_a && ( !p_sys->ctxA || !p_sys->p_src_a || !p_sys->p_dst_a ) ) ) |
|---|
| | 363 | ( b_has_a && ( !p_sys->ctxA || !p_sys->p_src_a || !p_sys->p_dst_a ) ) || |
|---|
| | 364 | ( p_sys->i_extend_factor != 1 && ( !p_sys->p_src_e || !p_sys->p_dst_e ) ) ) |
|---|
| 337 | 365 | { |
|---|
| 338 | 366 | msg_Err( p_filter, "could not init SwScaler and/or allocate memory" ); |
|---|
| … | … | |
| 344 | 372 | p_sys->fmt_out = *p_fmto; |
|---|
| 345 | 373 | |
|---|
| 346 | | msg_Err( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s", |
|---|
| | 374 | #if 0 |
|---|
| | 375 | msg_Dbg( p_filter, "%ix%i chroma: %4.4s -> %ix%i chroma: %4.4s extend by %d", |
|---|
| 347 | 376 | p_fmti->i_width, p_fmti->i_height, (char *)&p_fmti->i_chroma, |
|---|
| 348 | | p_fmto->i_width, p_fmto->i_height, (char *)&p_fmto->i_chroma ); |
|---|
| 349 | | |
|---|
| 350 | | |
|---|
| | 377 | p_fmto->i_width, p_fmto->i_height, (char *)&p_fmto->i_chroma, |
|---|
| | 378 | p_sys->i_extend_factor ); |
|---|
| | 379 | #endif |
|---|
| 351 | 380 | return VLC_SUCCESS; |
|---|
| 352 | 381 | } |
|---|
| … | … | |
| 354 | 383 | { |
|---|
| 355 | 384 | filter_sys_t *p_sys = p_filter->p_sys; |
|---|
| | 385 | |
|---|
| | 386 | if( p_sys->p_src_e ) |
|---|
| | 387 | picture_Release( p_sys->p_src_e ); |
|---|
| | 388 | if( p_sys->p_dst_e ) |
|---|
| | 389 | picture_Release( p_sys->p_dst_e ); |
|---|
| 356 | 390 | |
|---|
| 357 | 391 | if( p_sys->p_src_a ) |
|---|
| … | … | |
| 359 | 393 | if( p_sys->p_dst_a ) |
|---|
| 360 | 394 | picture_Release( p_sys->p_dst_a ); |
|---|
| | 395 | |
|---|
| 361 | 396 | if( p_sys->ctxA ) |
|---|
| 362 | 397 | sws_freeContext( p_sys->ctxA ); |
|---|
| … | … | |
| 370 | 405 | p_sys->p_src_a = NULL; |
|---|
| 371 | 406 | p_sys->p_dst_a = NULL; |
|---|
| | 407 | p_sys->p_src_e = NULL; |
|---|
| | 408 | p_sys->p_dst_e = NULL; |
|---|
| 372 | 409 | } |
|---|
| 373 | 410 | |
|---|
| … | … | |
| 376 | 413 | int i_plane_start, int i_plane_count ) |
|---|
| 377 | 414 | { |
|---|
| 378 | | for( int n = 0; n < __MIN(i_plane_count, p_picture->i_planes-i_plane_start ); n++ ) |
|---|
| | 415 | int n; |
|---|
| | 416 | for( n = 0; n < __MIN(i_plane_count, p_picture->i_planes-i_plane_start ); n++ ) |
|---|
| 379 | 417 | { |
|---|
| 380 | 418 | pp_pixel[n] = p_picture->p[i_plane_start+n].p_pixels; |
|---|
| 381 | 419 | pi_pitch[n] = p_picture->p[i_plane_start+n].i_pitch; |
|---|
| 382 | 420 | } |
|---|
| | 421 | for( ; n < 3; n++ ) |
|---|
| | 422 | { |
|---|
| | 423 | pp_pixel[n] = NULL; |
|---|
| | 424 | pi_pitch[n] = 0; |
|---|
| | 425 | } |
|---|
| 383 | 426 | } |
|---|
| 384 | 427 | |
|---|
| 385 | 428 | /* XXX is it always 3 even for BIG_ENDIAN (blend.c seems to think so) ? */ |
|---|
| 386 | 429 | #define OFFSET_A (3) |
|---|
| 387 | | static void ExtractA( picture_t *p_dst, const picture_t *p_src, const video_format_t *p_fmt ) |
|---|
| | 430 | static void ExtractA( picture_t *p_dst, const picture_t *p_src, unsigned i_width, unsigned i_height ) |
|---|
| 388 | 431 | { |
|---|
| 389 | 432 | plane_t *d = &p_dst->p[0]; |
|---|
| 390 | 433 | const plane_t *s = &p_src->p[0]; |
|---|
| 391 | 434 | |
|---|
| 392 | | for( unsigned y = 0; y < p_fmt->i_height; y++ ) |
|---|
| 393 | | for( unsigned x = 0; x < p_fmt->i_width; x++ ) |
|---|
| | 435 | for( unsigned y = 0; y < i_height; y++ ) |
|---|
| | 436 | for( unsigned x = 0; x < i_width; x++ ) |
|---|
| 394 | 437 | d->p_pixels[y*d->i_pitch+x] = s->p_pixels[y*s->i_pitch+4*x+OFFSET_A]; |
|---|
| 395 | 438 | } |
|---|
| 396 | | static void InjectA( picture_t *p_dst, const picture_t *p_src, const video_format_t *p_fmt ) |
|---|
| | 439 | static void InjectA( picture_t *p_dst, const picture_t *p_src, unsigned i_width, unsigned i_height ) |
|---|
| 397 | 440 | { |
|---|
| 398 | 441 | plane_t *d = &p_dst->p[0]; |
|---|
| 399 | 442 | const plane_t *s = &p_src->p[0]; |
|---|
| 400 | 443 | |
|---|
| 401 | | for( unsigned y = 0; y < p_fmt->i_height; y++ ) |
|---|
| 402 | | for( unsigned x = 0; x < p_fmt->i_width; x++ ) |
|---|
| | 444 | for( unsigned y = 0; y < i_height; y++ ) |
|---|
| | 445 | for( unsigned x = 0; x < i_width; x++ ) |
|---|
| 403 | 446 | d->p_pixels[y*d->i_pitch+4*x+OFFSET_A] = s->p_pixels[y*s->i_pitch+x]; |
|---|
| 404 | 447 | } |
|---|
| 405 | 448 | #undef OFFSET_A |
|---|
| 406 | 449 | |
|---|
| | 450 | static void CopyPad( picture_t *p_dst, const picture_t *p_src ) |
|---|
| | 451 | { |
|---|
| | 452 | picture_Copy( p_dst, p_src ); |
|---|
| | 453 | for( int n = 0; n < p_dst->i_planes; n++ ) |
|---|
| | 454 | { |
|---|
| | 455 | const plane_t *s = &p_src->p[n]; |
|---|
| | 456 | plane_t *d = &p_dst->p[n]; |
|---|
| | 457 | |
|---|
| | 458 | for( int y = 0; y < s->i_lines; y++ ) |
|---|
| | 459 | { |
|---|
| | 460 | for( int x = s->i_visible_pitch; x < d->i_visible_pitch; x += s->i_pixel_pitch ) |
|---|
| | 461 | 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 ); |
|---|
| | 462 | } |
|---|
| | 463 | } |
|---|
| | 464 | } |
|---|
| | 465 | |
|---|
| 407 | 466 | static void Convert( struct SwsContext *ctx, |
|---|
| 408 | | picture_t *p_dst, picture_t *p_src, const video_format_t *p_fmti, int i_plane_start, int i_plane_count ) |
|---|
| | 467 | picture_t *p_dst, picture_t *p_src, int i_height, int i_plane_start, int i_plane_count ) |
|---|
| 409 | 468 | { |
|---|
| 410 | 469 | uint8_t *src[3]; int src_stride[3]; |
|---|
| … | … | |
| 415 | 474 | |
|---|
| 416 | 475 | #if LIBSWSCALE_VERSION_INT >= ((0<<16)+(5<<8)+0) |
|---|
| 417 | | sws_scale( ctx, src, src_stride, 0, p_fmti->i_height, |
|---|
| | 476 | sws_scale( ctx, src, src_stride, 0, i_height, |
|---|
| 418 | 477 | dst, dst_stride ); |
|---|
| 419 | 478 | #else |
|---|
| 420 | | sws_scale_ordered( ctx, src, src_stride, 0, p_fmti->i_height, |
|---|
| | 479 | sws_scale_ordered( ctx, src, src_stride, 0, i_height, |
|---|
| 421 | 480 | dst, dst_stride ); |
|---|
| 422 | 481 | #endif |
|---|
| … | … | |
| 450 | 509 | } |
|---|
| 451 | 510 | |
|---|
| 452 | | Convert( p_sys->ctx, p_pic_dst, p_pic, p_fmti, 0, 3 ); |
|---|
| | 511 | /* */ |
|---|
| | 512 | picture_t *p_src = p_pic; |
|---|
| | 513 | picture_t *p_dst = p_pic_dst; |
|---|
| | 514 | if( p_sys->i_extend_factor != 1 ) |
|---|
| | 515 | { |
|---|
| | 516 | p_src = p_sys->p_src_e; |
|---|
| | 517 | p_dst = p_sys->p_dst_e; |
|---|
| | 518 | |
|---|
| | 519 | CopyPad( p_src, p_pic ); |
|---|
| | 520 | } |
|---|
| | 521 | |
|---|
| | 522 | Convert( p_sys->ctx, p_dst, p_src, p_fmti->i_height, 0, 3 ); |
|---|
| 453 | 523 | if( p_sys->ctxA ) |
|---|
| 454 | 524 | { |
|---|
| … | … | |
| 456 | 526 | { |
|---|
| 457 | 527 | /* We extract the A plane to rescale it, and then we reinject it. */ |
|---|
| 458 | | ExtractA( p_sys->p_src_a, p_pic, p_fmti ); |
|---|
| 459 | | |
|---|
| 460 | | Convert( p_sys->ctxA, p_sys->p_dst_a, p_sys->p_src_a, p_fmti, 0, 1 ); |
|---|
| 461 | | |
|---|
| 462 | | InjectA( p_pic_dst, p_sys->p_dst_a, p_fmto ); |
|---|
| | 528 | ExtractA( p_sys->p_src_a, p_src, p_fmti->i_width * p_sys->i_extend_factor, p_fmti->i_height ); |
|---|
| | 529 | |
|---|
| | 530 | Convert( p_sys->ctxA, p_sys->p_dst_a, p_sys->p_src_a, p_fmti->i_height, 0, 1 ); |
|---|
| | 531 | |
|---|
| | 532 | InjectA( p_dst, p_sys->p_dst_a, p_fmto->i_width * p_sys->i_extend_factor, p_fmto->i_height ); |
|---|
| 463 | 533 | } |
|---|
| 464 | 534 | else |
|---|
| 465 | 535 | { |
|---|
| 466 | | Convert( p_sys->ctxA, p_pic_dst, p_pic, p_fmti, 3, 1 ); |
|---|
| | 536 | Convert( p_sys->ctxA, p_dst, p_src, p_fmti->i_height, 3, 1 ); |
|---|
| 467 | 537 | } |
|---|
| | 538 | } |
|---|
| | 539 | |
|---|
| | 540 | if( p_sys->i_extend_factor != 1 ) |
|---|
| | 541 | { |
|---|
| | 542 | picture_CopyPixels( p_pic_dst, p_dst ); |
|---|
| 468 | 543 | } |
|---|
| 469 | 544 | |
|---|