| 92 | | #define CROPTOP_TEXT N_("Video crop (top)") |
|---|
| 93 | | #define CROPTOP_LONGTEXT N_( \ |
|---|
| 94 | | "Number of pixels to crop at the top of the video." ) |
|---|
| 95 | | #define CROPLEFT_TEXT N_("Video crop (left)") |
|---|
| 96 | | #define CROPLEFT_LONGTEXT N_( \ |
|---|
| 97 | | "Number of pixels to crop at the left of the video." ) |
|---|
| 98 | | #define CROPBOTTOM_TEXT N_("Video crop (bottom)") |
|---|
| 99 | | #define CROPBOTTOM_LONGTEXT N_( \ |
|---|
| 100 | | "Number of pixels to crop at the bottom of the video." ) |
|---|
| 101 | | #define CROPRIGHT_TEXT N_("Video crop (right)") |
|---|
| 102 | | #define CROPRIGHT_LONGTEXT N_( \ |
|---|
| 103 | | "Number of pixels to crop at the right of the video." ) |
|---|
| 104 | | |
|---|
| 105 | | #define PADDTOP_TEXT N_("Video padding (top)") |
|---|
| 106 | | #define PADDTOP_LONGTEXT N_( \ |
|---|
| 107 | | "Size of the black border to add at the top of the video." ) |
|---|
| 108 | | #define PADDLEFT_TEXT N_("Video padding (left)") |
|---|
| 109 | | #define PADDLEFT_LONGTEXT N_( \ |
|---|
| 110 | | "Size of the black border to add at the left of the video." ) |
|---|
| 111 | | #define PADDBOTTOM_TEXT N_("Video padding (bottom)") |
|---|
| 112 | | #define PADDBOTTOM_LONGTEXT N_( \ |
|---|
| 113 | | "Size of the black border to add at the bottom of the video." ) |
|---|
| 114 | | #define PADDRIGHT_TEXT N_("Video padding (right)") |
|---|
| 115 | | #define PADDRIGHT_LONGTEXT N_( \ |
|---|
| 116 | | "Size of the black border to add at the right of the video." ) |
|---|
| 117 | | |
|---|
| 118 | | #define CANVAS_WIDTH_TEXT N_("Video canvas width") |
|---|
| 119 | | #define CANVAS_WIDTH_LONGTEXT N_( \ |
|---|
| 120 | | "This will automatically crod and pad the video to a specified width." ) |
|---|
| 121 | | #define CANVAS_HEIGHT_TEXT N_("Video canvas height") |
|---|
| 122 | | #define CANVAS_HEIGHT_LONGTEXT N_( \ |
|---|
| 123 | | "This will automatically crod and pad the video to a specified height." ) |
|---|
| 124 | | #define CANVAS_ASPECT_TEXT N_("Video canvas aspect ratio") |
|---|
| 125 | | #define CANVAS_ASPECT_LONGTEXT N_( \ |
|---|
| 126 | | "This sets aspect (like 4:3) of the video canvas and letterbox the video "\ |
|---|
| 127 | | "accordingly." ) |
|---|
| 128 | | |
|---|
| 235 | | add_integer( SOUT_CFG_PREFIX "croptop", 0, NULL, CROPTOP_TEXT, |
|---|
| 236 | | CROPTOP_LONGTEXT, true ); |
|---|
| 237 | | add_integer( SOUT_CFG_PREFIX "cropleft", 0, NULL, CROPLEFT_TEXT, |
|---|
| 238 | | CROPLEFT_LONGTEXT, true ); |
|---|
| 239 | | add_integer( SOUT_CFG_PREFIX "cropbottom", 0, NULL, CROPBOTTOM_TEXT, |
|---|
| 240 | | CROPBOTTOM_LONGTEXT, true ); |
|---|
| 241 | | add_integer( SOUT_CFG_PREFIX "cropright", 0, NULL, CROPRIGHT_TEXT, |
|---|
| 242 | | CROPRIGHT_LONGTEXT, true ); |
|---|
| 243 | | |
|---|
| 244 | | add_integer( SOUT_CFG_PREFIX "paddtop", 0, NULL, PADDTOP_TEXT, |
|---|
| 245 | | PADDTOP_LONGTEXT, true ); |
|---|
| 246 | | add_integer( SOUT_CFG_PREFIX "paddleft", 0, NULL, PADDLEFT_TEXT, |
|---|
| 247 | | PADDLEFT_LONGTEXT, true ); |
|---|
| 248 | | add_integer( SOUT_CFG_PREFIX "paddbottom", 0, NULL, PADDBOTTOM_TEXT, |
|---|
| 249 | | PADDBOTTOM_LONGTEXT, true ); |
|---|
| 250 | | add_integer( SOUT_CFG_PREFIX "paddright", 0, NULL, PADDRIGHT_TEXT, |
|---|
| 251 | | PADDRIGHT_LONGTEXT, true ); |
|---|
| 252 | | |
|---|
| 253 | | add_integer( SOUT_CFG_PREFIX "canvas-width", 0, NULL, CANVAS_WIDTH_TEXT, |
|---|
| 254 | | CANVAS_WIDTH_LONGTEXT, true ); |
|---|
| 255 | | add_integer( SOUT_CFG_PREFIX "canvas-height", 0, NULL, CANVAS_HEIGHT_TEXT, |
|---|
| 256 | | CANVAS_HEIGHT_LONGTEXT, true ); |
|---|
| 257 | | add_string( SOUT_CFG_PREFIX "canvas-aspect", NULL, NULL, CANVAS_ASPECT_TEXT, |
|---|
| 258 | | CANVAS_ASPECT_LONGTEXT, false ); |
|---|
| 259 | | |
|---|
| 646 | | } |
|---|
| 647 | | free( val.psz_string ); |
|---|
| 648 | | |
|---|
| 649 | | var_Get( p_stream, SOUT_CFG_PREFIX "croptop", &val ); |
|---|
| 650 | | p_sys->i_crop_top = val.i_int; |
|---|
| 651 | | var_Get( p_stream, SOUT_CFG_PREFIX "cropbottom", &val ); |
|---|
| 652 | | p_sys->i_crop_bottom = val.i_int; |
|---|
| 653 | | var_Get( p_stream, SOUT_CFG_PREFIX "cropleft", &val ); |
|---|
| 654 | | p_sys->i_crop_left = val.i_int; |
|---|
| 655 | | var_Get( p_stream, SOUT_CFG_PREFIX "cropright", &val ); |
|---|
| 656 | | p_sys->i_crop_right = val.i_int; |
|---|
| 657 | | |
|---|
| 658 | | var_Get( p_stream, SOUT_CFG_PREFIX "paddtop", &val ); |
|---|
| 659 | | p_sys->i_padd_top = val.i_int; |
|---|
| 660 | | var_Get( p_stream, SOUT_CFG_PREFIX "paddbottom", &val ); |
|---|
| 661 | | p_sys->i_padd_bottom = val.i_int; |
|---|
| 662 | | var_Get( p_stream, SOUT_CFG_PREFIX "paddleft", &val ); |
|---|
| 663 | | p_sys->i_padd_left = val.i_int; |
|---|
| 664 | | var_Get( p_stream, SOUT_CFG_PREFIX "paddright", &val ); |
|---|
| 665 | | p_sys->i_padd_right = val.i_int; |
|---|
| 666 | | |
|---|
| 667 | | var_Get( p_stream, SOUT_CFG_PREFIX "canvas-width", &val ); |
|---|
| 668 | | p_sys->i_canvas_width = val.i_int; |
|---|
| 669 | | var_Get( p_stream, SOUT_CFG_PREFIX "canvas-height", &val ); |
|---|
| 670 | | p_sys->i_canvas_height = val.i_int; |
|---|
| 671 | | |
|---|
| 672 | | var_Get( p_stream, SOUT_CFG_PREFIX "canvas-aspect", &val ); |
|---|
| 673 | | p_sys->i_canvas_aspect = 0; |
|---|
| 674 | | if( val.psz_string && *val.psz_string ) |
|---|
| 675 | | { |
|---|
| 676 | | char *psz_parser = strchr( val.psz_string, ':' ); |
|---|
| 677 | | if( psz_parser ) |
|---|
| 678 | | { |
|---|
| 679 | | *psz_parser++ = '\0'; |
|---|
| 680 | | p_sys->i_canvas_aspect = atoi( val.psz_string ) * |
|---|
| 681 | | VOUT_ASPECT_FACTOR / atoi( psz_parser ); |
|---|
| 682 | | } |
|---|
| 683 | | else msg_Warn( p_stream, "bad aspect ratio %s", val.psz_string ); |
|---|
| 684 | | |
|---|
| 1991 | | |
|---|
| 1992 | | /* Correct scaling for target aspect ratio |
|---|
| 1993 | | * Shrink video if necessary |
|---|
| 1994 | | */ |
|---|
| 1995 | | if ( p_sys->i_canvas_aspect > 0 ) |
|---|
| 1996 | | { |
|---|
| 1997 | | float f_target_aspect = (float)p_sys->i_canvas_aspect / |
|---|
| 1998 | | VOUT_ASPECT_FACTOR; |
|---|
| 1999 | | |
|---|
| 2000 | | if( p_sys->i_canvas_width > 0 && p_sys->i_canvas_height > 0) |
|---|
| 2001 | | { |
|---|
| 2002 | | /* Calculate pixel aspect of canvas */ |
|---|
| 2003 | | f_target_aspect = f_target_aspect / p_sys->i_canvas_width * |
|---|
| 2004 | | p_sys->i_canvas_height; |
|---|
| 2005 | | } |
|---|
| 2006 | | if( f_target_aspect > f_aspect ) |
|---|
| 2007 | | { |
|---|
| 2008 | | /* Reduce width scale to increase aspect */ |
|---|
| 2009 | | f_scale_width = f_scale_width * f_aspect / f_target_aspect; |
|---|
| 2010 | | } |
|---|
| 2011 | | else |
|---|
| 2012 | | { |
|---|
| 2013 | | /* Reduce height scale to decrease aspect */ |
|---|
| 2014 | | f_scale_height = f_scale_height * f_target_aspect / f_aspect; |
|---|
| 2015 | | } |
|---|
| 2016 | | f_aspect = f_target_aspect; |
|---|
| 2017 | | msg_Dbg( p_stream, "canvas scaled pixel aspect is %f:1", f_aspect ); |
|---|
| 2018 | | } |
|---|
| 2024 | | i_dst_width = 2 * (int)( p_sys->i_crop_width * f_scale_width / 2 + 0.5 ); |
|---|
| 2025 | | i_dst_height = 2 * |
|---|
| 2026 | | (int)( p_sys->i_crop_height * f_scale_height / 2 + 0.5 ); |
|---|
| 2027 | | |
|---|
| 2028 | | p_sys->i_nopadd_width = i_dst_width; |
|---|
| 2029 | | p_sys->i_nopadd_height = i_dst_height; |
|---|
| 2030 | | p_sys->i_dst_x_offset = 0; |
|---|
| 2031 | | p_sys->i_dst_y_offset = 0; |
|---|
| 2032 | | |
|---|
| 2033 | | /* Handle canvas and padding */ |
|---|
| 2034 | | if( p_sys->i_canvas_width <= 0 ) |
|---|
| 2035 | | { |
|---|
| 2036 | | /* No canvas width set, add explicit padding border */ |
|---|
| 2037 | | i_dst_width = p_sys->i_nopadd_width + ( p_sys->i_padd_left & ~1 ) + |
|---|
| 2038 | | ( p_sys->i_padd_right & ~1 ); |
|---|
| 2039 | | p_sys->i_dst_x_offset = ( p_sys->i_padd_left & ~1 ); |
|---|
| 2040 | | } |
|---|
| 2041 | | else |
|---|
| 2042 | | { |
|---|
| 2043 | | /* Canvas set, check if we have to padd or crop */ |
|---|
| 2044 | | if( p_sys->i_canvas_width < p_sys->i_nopadd_width ) |
|---|
| 2045 | | { |
|---|
| 2046 | | /* need to crop more, but keep same scaling */ |
|---|
| 2047 | | int i_crop = 2 * (int)( ( p_sys->i_canvas_width & ~1 ) / |
|---|
| 2048 | | f_scale_width / 2 + 0.5 ); |
|---|
| 2049 | | |
|---|
| 2050 | | p_sys->i_src_x_offset += ( ( p_sys->i_crop_width - i_crop ) / 2 ) |
|---|
| 2051 | | & ~1; |
|---|
| 2052 | | p_sys->i_crop_width = i_crop; |
|---|
| 2053 | | i_dst_width = p_sys->i_canvas_width & ~1; |
|---|
| 2054 | | p_sys->i_nopadd_width = i_dst_width; |
|---|
| 2055 | | } |
|---|
| 2056 | | else if( p_sys->i_canvas_width > p_sys->i_nopadd_width ) |
|---|
| 2057 | | { |
|---|
| 2058 | | /* need to padd */ |
|---|
| 2059 | | i_dst_width = p_sys->i_canvas_width & ~1; |
|---|
| 2060 | | p_sys->i_dst_x_offset = ( i_dst_width - p_sys->i_nopadd_width )/2; |
|---|
| 2061 | | p_sys->i_dst_x_offset = p_sys->i_dst_x_offset & ~1; |
|---|
| 2062 | | } |
|---|
| 2063 | | } |
|---|
| 2064 | | |
|---|
| 2065 | | if( p_sys->i_canvas_height <= 0 ) |
|---|
| 2066 | | { |
|---|
| 2067 | | /* No canvas set, add padding border */ |
|---|
| 2068 | | i_dst_height = p_sys->i_nopadd_height + ( p_sys->i_padd_top & ~1 ) + |
|---|
| 2069 | | ( p_sys->i_padd_bottom & ~1 ); |
|---|
| 2070 | | p_sys->i_dst_y_offset = ( p_sys->i_padd_top & ~1 ); |
|---|
| 2071 | | } |
|---|
| 2072 | | else |
|---|
| 2073 | | { |
|---|
| 2074 | | /* Canvas set, check if we have to padd or crop */ |
|---|
| 2075 | | if( p_sys->i_canvas_height < p_sys->i_nopadd_height ) |
|---|
| 2076 | | { |
|---|
| 2077 | | /* need to crop more, but keep same scaling */ |
|---|
| 2078 | | int i_crop = 2 * (int)( ( p_sys->i_canvas_height & ~1 ) / |
|---|
| 2079 | | f_scale_height / 2 + 0.5 ); |
|---|
| 2080 | | |
|---|
| 2081 | | p_sys->i_src_y_offset += ( ( p_sys->i_crop_height - i_crop ) / 2 ) |
|---|
| 2082 | | & ~1; |
|---|
| 2083 | | p_sys->i_crop_height = i_crop; |
|---|
| 2084 | | i_dst_height = p_sys->i_canvas_height & ~1; |
|---|
| 2085 | | p_sys->i_nopadd_height = i_dst_height; |
|---|
| 2086 | | } |
|---|
| 2087 | | else if( p_sys->i_canvas_height > p_sys->i_nopadd_height ) |
|---|
| 2088 | | { |
|---|
| 2089 | | /* need to padd */ |
|---|
| 2090 | | i_dst_height = p_sys->i_canvas_height & ~1; |
|---|
| 2091 | | p_sys->i_dst_y_offset = ( i_dst_height - p_sys->i_nopadd_height ) |
|---|
| 2092 | | /2; |
|---|
| 2093 | | p_sys->i_dst_y_offset = p_sys->i_dst_y_offset & ~1; |
|---|
| 2094 | | } |
|---|
| 2095 | | } |
|---|
| | 1851 | i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5); |
|---|
| | 1852 | i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5); |
|---|
| 2341 | | /* FIXME don't take croppadding changes into account */ |
|---|
| 2342 | | NULL, "scale" ); |
|---|
| 2343 | | if( !id->pp_filter[id->i_filter] ) |
|---|
| 2344 | | { |
|---|
| 2345 | | es_format_t fmt_middle; |
|---|
| 2346 | | es_format_Copy( &fmt_middle, &id->p_decoder->fmt_out ); |
|---|
| 2347 | | fmt_middle.video.i_chroma = id->p_encoder->fmt_in.video.i_chroma; |
|---|
| 2348 | | |
|---|
| 2349 | | /* Try doing the chroma conversion first ... */ |
|---|
| 2350 | | if( id->p_decoder->fmt_out.video.i_chroma != |
|---|
| 2351 | | id->p_encoder->fmt_in.video.i_chroma ) |
|---|
| 2352 | | { |
|---|
| 2353 | | id->pp_filter[id->i_filter] = |
|---|
| 2354 | | transcode_video_filter_new( p_stream, |
|---|
| 2355 | | &id->p_decoder->fmt_out, &fmt_middle, |
|---|
| 2356 | | NULL, "chroma" ); /* FIXME: doesn't exist yet */ |
|---|
| 2357 | | if( !id->pp_filter[id->i_filter] ) |
|---|
| 2358 | | { |
|---|
| 2359 | | es_format_Clean( &fmt_middle ); |
|---|
| 2360 | | p_pic->pf_release( p_pic ); |
|---|
| 2361 | | transcode_video_close( p_stream, id ); |
|---|
| 2362 | | id->b_transcode = false; |
|---|
| 2363 | | return VLC_EGENERIC; |
|---|
| 2364 | | } |
|---|
| 2365 | | id->i_filter++; |
|---|
| 2366 | | } |
|---|
| 2367 | | |
|---|
| 2368 | | /* ... and then the scaling */ |
|---|
| 2369 | | if( ( id->p_decoder->fmt_out.video.i_width != |
|---|
| 2370 | | id->p_encoder->fmt_out.video.i_width ) || |
|---|
| 2371 | | ( id->p_decoder->fmt_out.video.i_height != |
|---|
| 2372 | | id->p_encoder->fmt_out.video.i_height ) ) |
|---|
| 2373 | | { |
|---|
| 2374 | | id->pp_filter[id->i_filter] = |
|---|
| 2375 | | transcode_video_filter_new( p_stream, |
|---|
| 2376 | | &fmt_middle, &id->p_encoder->fmt_in, |
|---|
| 2377 | | /* FIXME don't take croppadding changes into account */ |
|---|
| 2378 | | NULL, "scale" ); |
|---|
| 2379 | | if( !id->pp_filter[id->i_filter] ) |
|---|
| 2380 | | { |
|---|
| 2381 | | es_format_Clean( &fmt_middle ); |
|---|
| 2382 | | p_pic->pf_release( p_pic ); |
|---|
| 2383 | | transcode_video_close( p_stream, id ); |
|---|
| 2384 | | id->b_transcode = false; |
|---|
| 2385 | | return VLC_EGENERIC; |
|---|
| 2386 | | } |
|---|
| 2387 | | id->i_filter++; |
|---|
| 2388 | | } |
|---|
| 2389 | | es_format_Clean( &fmt_middle ); |
|---|
| 2390 | | } |
|---|
| 2391 | | else |
|---|
| 2392 | | id->i_filter++; |
|---|
| 2393 | | } |
|---|
| 2394 | | |
|---|
| 2395 | | /* Take care of croping and padding */ |
|---|
| 2396 | | if( (int)id->p_decoder->fmt_out.video.i_width != p_sys->i_crop_width || |
|---|
| 2397 | | p_sys->i_crop_width != p_sys->i_nopadd_width || |
|---|
| 2398 | | p_sys->i_nopadd_width != (int)id->p_encoder->fmt_out.video.i_width || |
|---|
| 2399 | | |
|---|
| 2400 | | (int)id->p_decoder->fmt_out.video.i_height != p_sys->i_crop_height || |
|---|
| 2401 | | p_sys->i_crop_height != p_sys->i_nopadd_height || |
|---|
| 2402 | | p_sys->i_nopadd_height != (int)id->p_encoder->fmt_out.video.i_height) |
|---|
| 2403 | | { |
|---|
| 2404 | | /* Set crop and padding information */ |
|---|
| 2405 | | es_format_t fmt_in, fmt_out; |
|---|
| 2406 | | es_format_Copy( &fmt_in, &id->p_encoder->fmt_in ); |
|---|
| 2407 | | fmt_in.video.i_x_offset = p_sys->i_src_x_offset; |
|---|
| 2408 | | fmt_in.video.i_y_offset = p_sys->i_src_y_offset; |
|---|
| 2409 | | fmt_in.video.i_visible_width = p_sys->i_crop_width; |
|---|
| 2410 | | fmt_in.video.i_visible_height = p_sys->i_crop_height; |
|---|
| 2411 | | |
|---|
| 2412 | | es_format_Copy( &fmt_in, &id->p_encoder->fmt_in ); |
|---|
| 2413 | | fmt_out.video.i_x_offset = p_sys->i_dst_x_offset; |
|---|
| 2414 | | fmt_out.video.i_y_offset = p_sys->i_dst_y_offset; |
|---|
| 2415 | | fmt_out.video.i_visible_width = id->p_encoder->fmt_in.video.i_width;// p_sys->i_nopadd_width; |
|---|
| 2416 | | fmt_out.video.i_visible_height = id->p_encoder->fmt_in.video.i_height; // p_sys->i_nopadd_height; |
|---|
| 2417 | | |
|---|
| 2418 | | id->pp_filter[id->i_filter] = |
|---|
| 2419 | | transcode_video_filter_new( p_stream, |
|---|
| 2420 | | &fmt_in, &fmt_out, NULL, "croppadd" ); |
|---|
| 2421 | | |
|---|
| 2422 | | es_format_Clean( &fmt_in ); |
|---|
| 2423 | | es_format_Clean( &fmt_out ); |
|---|
| 2424 | | |
|---|
| | 2095 | NULL, NULL ); |
|---|