diff options
author | jbrjake <[email protected]> | 2007-10-16 19:00:41 +0000 |
---|---|---|
committer | jbrjake <[email protected]> | 2007-10-16 19:00:41 +0000 |
commit | c832b1edbbff5692fdc6b55ec245e013d1b1dce9 (patch) | |
tree | 25ab3d8313fad66b1fb3284eebbfca0ab7649740 /libhb | |
parent | 3a86ddf273f92ad057e40f4b6f08545d3cef86a4 (diff) |
"Loose" anamorphic:
- Scales the storage frame size to arbitrary widths, like 640 for the iPod.
- Uses dimensions that divide cleanly by an arbitrary number (default: 16) and adjusts the SAR to match
- Uses ITU PAR values when the video is meant to be overscanned ( 7+ pixels cropped on left+right)
git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@1029 b64f7644-9d1e-0410-96f1-a4d463321fa5
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.h | 2 | ||||
-rw-r--r-- | libhb/hb.c | 150 | ||||
-rw-r--r-- | libhb/hb.h | 1 | ||||
-rw-r--r-- | libhb/work.c | 16 |
4 files changed, 166 insertions, 3 deletions
diff --git a/libhb/common.h b/libhb/common.h index e71959142..1cf6cdb59 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -27,6 +27,7 @@ #define EVEN( a ) ( (a) + ( (a) & 1 ) ) #define MULTIPLE_16( a ) ( 16 * ( ( (a) + 8 ) / 16 ) ) +#define MULTIPLE_MOD( a, b ) ( b * ( ( (a) + (b / 2) ) / b ) ) #define HB_DVD_READ_BUFFER_SIZE 2048 @@ -139,6 +140,7 @@ struct hb_job_s int pixel_ratio; int pixel_aspect_width; int pixel_aspect_height; + int modulus; int maxWidth; int maxHeight; diff --git a/libhb/hb.c b/libhb/hb.c index a53bd1f4a..6b108bdf0 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -427,6 +427,156 @@ void hb_get_preview( hb_handle_t * h, hb_title_t * title, int picture, } /** + * Calculates job width and height for anamorphic content. + * @param job Handle to hb_job_t. + */ +void hb_set_anamorphic_size( hb_job_t * job) +{ + hb_title_t * title = job->title; + + /* "Loose" anamorphic. + - Uses mod16-compliant dimensions, + - Allows users to set the width + - Handles ITU pixel aspects + */ + + /* Set up some variables to make the math easier to follow. */ + int cropped_width = title->width - job->crop[2] - job->crop[3] ; + int cropped_height = title->height - job->crop[0] - job->crop[1] ; + int storage_aspect = cropped_width * 10000 / cropped_height; + + /* Gotta handle bounding dimensions differently + than for non-anamorphic encodes: + If the width is too big, just reset it with no rescaling. + Instead of using the aspect-scaled job height, + we need to see if the job width divided by the storage aspect + is bigger than the max. If so, set it to the max (this is sloppy). + If not, set job height to job width divided by storage aspect. + */ + if ( job->maxWidth && (job->maxWidth < job->width) ) + job->width = job->maxWidth; + + if ( job->maxHeight && (job->maxHeight < (job->width / storage_aspect * 10000)) ) + { + job->height = job->maxHeight; + } + else + { + job->height = job->width * 10000 / storage_aspect; + } + + /* Time to get picture dimensions that divide cleanly. + These variables will store temporary dimensions as we iterate. */ + int i, w, h, mod; + + /* In case the user specified a modulus, use it */ + if (job->modulus) + mod = job->modulus; + else + mod = 16; + + /* Iterate through multiples of mod to find one close to job->width. */ + for( i = 1;; i++ ) + { + w = mod * i; + + if (w < job->width) + { + if ( ( job->width - w ) <= ( mod / 2 ) ) + /* We'll take a width that's + smaller, but close enough. */ + break; + } + if (w == job->width) + /* Mod 16 dimensions, how nice! */ + break; + if( w > job->width ) + { + if ( ( w - job->width ) < (mod/2) ) + /* We'll take a width that's bigger, if we have to. */ + break; + } + } + job->width = mod * (i); + + /* Now do the same for a mod-friendly value near job->height. */ + for( i = 1;; i++) + { + h = i * mod; + + if (h < job->height) + { + if ( ( job->height - h ) <= ( mod / 2 )) + /* Go with a smaller height, + if it's close enough. */ + break; + } + if (h == job->height) + /* Mod 16 dimensions, how nice! */ + break; + + if ( h > job->height) + { + if ( ( h - job->height ) < ( mod / 2 )) + /* Use a taller height if necessary */ + break; + } + } + job->height = mod * (i); + + if (cropped_width <= 706) + { + /* Handle ITU PARs */ + if (title->height == 480) + { + /* It's NTSC */ + if (title->aspect == 16) + { + /* It's widescreen */ + job->pixel_aspect_width = 40; + job->pixel_aspect_height = 33; + } + else + { + /* It's 4:3 */ + job->pixel_aspect_width = 10; + job->pixel_aspect_height = 11; + } + } + else if (title->height == 576) + { + /* It's PAL */ + if(title->aspect == 16) + { + /* It's widescreen */ + job->pixel_aspect_width = 16; + job->pixel_aspect_height = 11; + } + else + { + /* It's 4:3 */ + job->pixel_aspect_width = 12; + job->pixel_aspect_height = 11; + } + } + } + + /* Figure out what dimensions the source would display at. */ + int source_display_width = cropped_width * ((float)job->pixel_aspect_width / (float)job->pixel_aspect_height) ; + + /* The film AR is the source's display width / cropped source height. + The output display width is the output height * film AR. + The output PAR is the output display width / output storage width. */ + job->pixel_aspect_width = job->height * source_display_width / cropped_height; + job->pixel_aspect_height = job->width; + + /* While x264 is smart enough to reduce fractions on its own, libavcodec + needs some help with the math, so lose superfluous factors. */ + hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height, + job->pixel_aspect_width, job->pixel_aspect_height ); +} + +/** * Calculates job width, height, and cropping parameters. * @param job Handle to hb_job_t. * @param aspect Desired aspect ratio. Value of -1 uses title aspect. diff --git a/libhb/hb.h b/libhb/hb.h index 6f8af2aee..be629505f 100644 --- a/libhb/hb.h +++ b/libhb/hb.h @@ -78,6 +78,7 @@ hb_list_t * hb_get_titles( hb_handle_t * ); void hb_get_preview( hb_handle_t *, hb_title_t *, int, uint8_t * ); void hb_set_size( hb_job_t *, int ratio, int pixels ); +void hb_set_anamorphic_size( hb_job_t * ); /* Handling jobs */ int hb_count( hb_handle_t * ); diff --git a/libhb/work.c b/libhb/work.c index 72d12d75a..22e081532 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -128,16 +128,26 @@ static void do_job( hb_job_t * job, int cpu_count ) job->height=title->height-job->crop[0]-job->crop[1]; job->width=title->width-job->crop[2]-job->crop[3]; } + else if ( job->pixel_ratio == 2 ) + { + + /* While keeping the DVD storage aspect, resize the job width and height + so they fit into the user's specified dimensions. */ + hb_set_anamorphic_size(job); + } - /* Keep width and height within these boundaries */ - if (job->maxHeight && (job->height > job->maxHeight) ) + /* Keep width and height within these boundaries, + but ignore for "loose" anamorphic encodes, for + which this stuff is covered in the pixel_ratio + section right above.*/ + if (job->maxHeight && (job->height > job->maxHeight) && (job->pixel_ratio != 2)) { job->height = job->maxHeight; hb_fix_aspect( job, HB_KEEP_HEIGHT ); hb_log("Height out of bounds, scaling down to %i", job->maxHeight); hb_log("New dimensions %i * %i", job->width, job->height); } - if (job->maxWidth && (job->width > job->maxWidth) ) + if (job->maxWidth && (job->width > job->maxWidth) && (job->pixel_ratio != 2)) { job->width = job->maxWidth; hb_fix_aspect( job, HB_KEEP_WIDTH ); |