diff options
Diffstat (limited to 'libhb')
-rw-r--r-- | libhb/common.h | 16 | ||||
-rw-r--r-- | libhb/encavcodec.c | 8 | ||||
-rw-r--r-- | libhb/enctheora.c | 6 | ||||
-rw-r--r-- | libhb/encx264.c | 6 | ||||
-rw-r--r-- | libhb/encxvid.c | 6 | ||||
-rw-r--r-- | libhb/hb.c | 180 | ||||
-rw-r--r-- | libhb/muxavi.c | 8 | ||||
-rw-r--r-- | libhb/muxmkv.c | 4 | ||||
-rw-r--r-- | libhb/muxmp4.c | 6 | ||||
-rw-r--r-- | libhb/scan.c | 8 | ||||
-rw-r--r-- | libhb/work.c | 49 |
11 files changed, 179 insertions, 118 deletions
diff --git a/libhb/common.h b/libhb/common.h index e03769147..1121ae8ec 100644 --- a/libhb/common.h +++ b/libhb/common.h @@ -147,10 +147,18 @@ struct hb_job_s int height; int keep_ratio; int grayscale; - int pixel_ratio; - int pixel_aspect_width; - int pixel_aspect_height; - int modulus; + + struct + { + int mode; + int modulus; + int itu_par; + int par_width; + int par_height; + int dar_width; + int dar_height; + } anamorphic; + int maxWidth; int maxHeight; diff --git a/libhb/encavcodec.c b/libhb/encavcodec.c index b0cf04e2f..22eb286d5 100644 --- a/libhb/encavcodec.c +++ b/libhb/encavcodec.c @@ -106,13 +106,13 @@ int encavcodecInit( hb_work_object_t * w, hb_job_t * job ) context->gop_size = 10 * job->vrate / job->vrate_base; context->pix_fmt = PIX_FMT_YUV420P; - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { - context->sample_aspect_ratio.num = job->pixel_aspect_width; - context->sample_aspect_ratio.den = job->pixel_aspect_height; + context->sample_aspect_ratio.num = job->anamorphic.par_width; + context->sample_aspect_ratio.den = job->anamorphic.par_height; hb_log( "encavcodec: encoding with stored aspect %d/%d", - job->pixel_aspect_width, job->pixel_aspect_height ); + job->anamorphic.par_width, job->anamorphic.par_height ); } if( job->mux & ( HB_MUX_MP4 | HB_MUX_PSP ) ) diff --git a/libhb/enctheora.c b/libhb/enctheora.c index bcc27eb4d..e340bade5 100644 --- a/libhb/enctheora.c +++ b/libhb/enctheora.c @@ -42,10 +42,10 @@ int enctheoraInit( hb_work_object_t * w, hb_job_t * job ) ti.offset_x = ti.offset_y = 0; ti.fps_numerator = job->vrate; ti.fps_denominator = job->vrate_base; - if (job->pixel_ratio) + if( job->anamorphic.mode ) { - ti.aspect_numerator = job->pixel_aspect_width; - ti.aspect_denominator = job->pixel_aspect_height; + ti.aspect_numerator = job->anamorphic.par_width; + ti.aspect_denominator = job->anamorphic.par_height; } else { diff --git a/libhb/encx264.c b/libhb/encx264.c index 97de03e8e..eb8d8426d 100644 --- a/libhb/encx264.c +++ b/libhb/encx264.c @@ -224,10 +224,10 @@ int encx264Init( hb_work_object_t * w, hb_job_t * job ) param.vui.i_colmatrix = 6; } - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { - param.vui.i_sar_width = job->pixel_aspect_width; - param.vui.i_sar_height = job->pixel_aspect_height; + param.vui.i_sar_width = job->anamorphic.par_width; + param.vui.i_sar_height = job->anamorphic.par_height; hb_log( "encx264: encoding with stored aspect %d/%d", param.vui.i_sar_width, param.vui.i_sar_height ); diff --git a/libhb/encxvid.c b/libhb/encxvid.c index cb4ca01fe..6feadb770 100644 --- a/libhb/encxvid.c +++ b/libhb/encxvid.c @@ -173,11 +173,11 @@ int encxvidWork( hb_work_object_t * w, hb_buffer_t ** buf_in, frame.vol_flags = 0; frame.vop_flags = XVID_VOP_HALFPEL | XVID_VOP_INTER4V | XVID_VOP_TRELLISQUANT | XVID_VOP_HQACPRED; - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { frame.par = XVID_PAR_EXT; - frame.par_width = job->pixel_aspect_width; - frame.par_height = job->pixel_aspect_height; + frame.par_width = job->anamorphic.par_width; + frame.par_height = job->anamorphic.par_height; } if( job->grayscale ) diff --git a/libhb/hb.c b/libhb/hb.c index 6c0aabc7a..08bea4bf2 100644 --- a/libhb/hb.c +++ b/libhb/hb.c @@ -583,60 +583,20 @@ void hb_set_anamorphic_size( hb_job_t * job, int *output_width, int *output_height, int *output_par_width, int *output_par_height ) { - /* "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. */ hb_title_t * title = job->title; int cropped_width = title->width - job->crop[2] - job->crop[3] ; int cropped_height = title->height - job->crop[0] - job->crop[1] ; double storage_aspect = (double)cropped_width / (double)cropped_height; - int width = job->width; - int height; // Gets set later, ignore user job->height value - int mod = job->modulus; + int mod = job->anamorphic.modulus ? job->anamorphic.modulus : 16; double aspect = title->aspect; - - /* 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) ) - width = job->maxWidth; - - height = ((double)width / storage_aspect) + 0.5; - if ( job->maxHeight && (job->maxHeight < height) ) - height = job->maxHeight; - - /* In case the user specified a modulus, use it */ - if (job->modulus) - mod = job->modulus; - else - mod = 16; - - /* Time to get picture dimensions that divide cleanly.*/ - width = MULTIPLE_MOD( width, mod); - height = MULTIPLE_MOD( height, mod); - - /* Verify these new dimensions don't violate max height and width settings */ - if ( job->maxWidth && (job->maxWidth < job->width) ) - width = job->maxWidth; - if ( job->maxHeight && (job->maxHeight < height) ) - height = job->maxHeight; - int pixel_aspect_width = job->pixel_aspect_width; - int pixel_aspect_height = job->pixel_aspect_height; - - /* If a source was really 704*480 and hard matted with cropping - to 720*480, replace the PAR values with the ITU broadcast ones. */ - if (title->width == 720 && cropped_width <= 706) + int pixel_aspect_width = job->anamorphic.par_width; + int pixel_aspect_height = job->anamorphic.par_height; + + /* If a source was really NTSC or PAL and the user specified ITU PAR + values, replace the standard PAR values with the ITU broadcast ones. */ + if( title->width == 720 && job->anamorphic.itu_par ) { // convert aspect to a scaled integer so we can test for 16:9 & 4:3 // aspect ratios ignoring insignificant differences in the LSBs of @@ -678,20 +638,122 @@ void hb_set_anamorphic_size( hb_job_t * job, } } - /* Figure out what dimensions the source would display at. */ + /* Figure out what width the source would display at. */ int source_display_width = cropped_width * (double)pixel_aspect_width / (double)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. */ - pixel_aspect_width = height * source_display_width / cropped_height; - pixel_aspect_height = width; - - /* Pass the results back to the caller */ - *output_width = width; - *output_height = height; - + + /* + 3 different ways of deciding output dimensions: + - 1: Strict anamorphic, preserve source dimensions + - 2: Loose anamorphic, round to mod16 and preserve storage aspect ratio + - 3: Power user anamorphic, specify everything + */ + int width, height; + switch( job->anamorphic.mode ) + { + case 1: + /* Strict anamorphic */ + *output_width = cropped_width; + *output_height = cropped_height; + *output_par_width = title->pixel_aspect_width; + *output_par_height = title->pixel_aspect_height; + break; + + case 2: + /* "Loose" anamorphic. + - Uses mod16-compliant dimensions, + - Allows users to set the width + */ + width = job->width; + height; // Gets set later, ignore user job->height value + + /* Gotta handle bounding dimensions. + 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) ) + width = job->maxWidth; + height = ((double)width / storage_aspect) + 0.5; + + if ( job->maxHeight && (job->maxHeight < height) ) + height = job->maxHeight; + + /* Time to get picture dimensions that divide cleanly.*/ + width = MULTIPLE_MOD( width, mod); + height = MULTIPLE_MOD( height, mod); + + /* Verify these new dimensions don't violate max height and width settings */ + if ( job->maxWidth && (job->maxWidth < job->width) ) + width = job->maxWidth; + if ( job->maxHeight && (job->maxHeight < height) ) + height = job->maxHeight; + + /* 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. */ + pixel_aspect_width = height * source_display_width / cropped_height; + pixel_aspect_height = width; + + /* Pass the results back to the caller */ + *output_width = width; + *output_height = height; + break; + + case 3: + /* Anamorphic 3: Power User Jamboree + - Set everything based on specified values */ + + /* Use specified storage dimensions */ + width = job->width; + height = job->height; + + /* Bind to max dimensions */ + if( job->maxWidth && width > job->maxWidth ) + width = job->maxWidth; + if( job->maxHeight && height > job->maxHeight ) + height = job->maxHeight; + + /* Time to get picture dimensions that divide cleanly.*/ + width = MULTIPLE_MOD( width, mod); + height = MULTIPLE_MOD( height, mod); + + /* Verify we're still within max dimensions */ + if( job->maxWidth && width > job->maxWidth ) + width = job->maxWidth - (mod/2); + if( job->maxHeight && height > job->maxHeight ) + height = job->maxHeight - (mod/2); + + /* Re-ensure we have picture dimensions that divide cleanly. */ + width = MULTIPLE_MOD( width, mod ); + height = MULTIPLE_MOD( height, mod ); + + /* That finishes the storage dimensions. On to display. */ + if( job->anamorphic.dar_width && job->anamorphic.dar_height ) + { + /* We need to adjust the PAR to produce this aspect. */ + pixel_aspect_width = height * job->anamorphic.dar_width / job->anamorphic.dar_height; + pixel_aspect_height = width; + } + else + { + /* We first need the display ar. + That's the source display width divided by the source height after cropping. + Then we multiple the output height by that to get the pixel aspect width, + and the pixel aspect height is the storage width.*/ + pixel_aspect_width = height * source_display_width / cropped_height; + pixel_aspect_height = width; + } + + /* Back to caller */ + *output_width = width; + *output_height = height; + break; + } + /* While x264 is smart enough to reduce fractions on its own, libavcodec needs some help with the math, so lose superfluous factors. */ hb_reduce( output_par_width, output_par_height, diff --git a/libhb/muxavi.c b/libhb/muxavi.c index 70d22f522..913e84508 100644 --- a/libhb/muxavi.c +++ b/libhb/muxavi.c @@ -394,7 +394,7 @@ static int AVIInit( hb_mux_object_t * m ) #define g mux_data->vprp_header /* Vprp video stream header */ - AVRational sample_aspect_ratio = ( AVRational ){ job->pixel_aspect_width, job->pixel_aspect_height }; + AVRational sample_aspect_ratio = ( AVRational ){ job->anamorphic.par_width, job->anamorphic.par_height }; AVRational dar = av_mul_q( sample_aspect_ratio, ( AVRational ){ job->width, job->height } ); int num, den; av_reduce(&num, &den, dar.num, dar.den, 0xFFFF); @@ -490,7 +490,7 @@ static int AVIInit( hb_mux_object_t * m ) /* video strf */ sizeof( hb_bitmap_info_t ) + /* video vprp */ - ( job->pixel_ratio ? sizeof( hb_avi_vprp_info_t ) : 0 ) + + ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) + /* audios strf */ audio_count * ( sizeof( hb_wave_formatex_t ) + ( is_ac3 ? 0 : sizeof( hb_wave_mp3_t ) ) ); @@ -513,11 +513,11 @@ static int AVIInit( hb_mux_object_t * m ) WriteInt32( m->file, FOURCC( "LIST" ) ); WriteInt32( m->file, 4 + sizeof( hb_avi_stream_header_t ) + sizeof( hb_bitmap_info_t ) + - ( job->pixel_ratio ? sizeof( hb_avi_vprp_info_t ) : 0 ) ); + ( job->anamorphic.mode ? sizeof( hb_avi_vprp_info_t ) : 0 ) ); WriteInt32( m->file, FOURCC( "strl" ) ); WriteStreamHeader( m->file, &mux_data->header ); WriteBitmapInfo( m->file, &mux_data->format.v ); - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { WriteVprpInfo( m->file, &mux_data->vprp_header ); } diff --git a/libhb/muxmkv.c b/libhb/muxmkv.c index 23d1b8aca..a68e6896d 100644 --- a/libhb/muxmkv.c +++ b/libhb/muxmkv.c @@ -138,9 +138,9 @@ static int MKVInit( hb_mux_object_t * m ) track->extra.video.pixelWidth = job->width; track->extra.video.pixelHeight = job->height; track->extra.video.displayHeight = job->height; - if(job->pixel_ratio) + if( job->anamorphic.mode ) { - track->extra.video.displayWidth = job->width * ((double)job->pixel_aspect_width / (double)job->pixel_aspect_height); + track->extra.video.displayWidth = job->width * ((double)job->anamorphic.par_width / (double)job->anamorphic.par_height); } else { diff --git a/libhb/muxmp4.c b/libhb/muxmp4.c index 11523a9d6..1c82211d9 100644 --- a/libhb/muxmp4.c +++ b/libhb/muxmp4.c @@ -183,14 +183,14 @@ static int MP4Init( hb_mux_object_t * m ) MP4AddColr(m->file, mux_data->track, 6, 1, 6); } - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { /* PASP atom for anamorphic video */ float width, height; - width = job->pixel_aspect_width; + width = job->anamorphic.par_width; - height = job->pixel_aspect_height; + height = job->anamorphic.par_height; MP4AddPixelAspectRatio(m->file, mux_data->track, (uint32_t)width, (uint32_t)height); diff --git a/libhb/scan.c b/libhb/scan.c index 6cdaceb62..aa91838f3 100644 --- a/libhb/scan.c +++ b/libhb/scan.c @@ -192,14 +192,14 @@ static void ScanFunc( void * _data ) /* Preserve a source's pixel aspect, if it's available. */ if( title->pixel_aspect_width && title->pixel_aspect_height ) { - job->pixel_aspect_width = title->pixel_aspect_width; - job->pixel_aspect_height = title->pixel_aspect_height; + job->anamorphic.par_width = title->pixel_aspect_width; + job->anamorphic.par_height = title->pixel_aspect_height; } if( title->aspect != 0 && title->aspect != 1. && - !job->pixel_aspect_width && !job->pixel_aspect_height) + !job->anamorphic.par_width && !job->anamorphic.par_height) { - hb_reduce( &job->pixel_aspect_width, &job->pixel_aspect_height, + hb_reduce( &job->anamorphic.par_width, &job->anamorphic.par_height, (int)(title->aspect * title->height + 0.5), title->width ); } diff --git a/libhb/work.c b/libhb/work.c index 0d57dd4ff..4ea0f5ebd 100644 --- a/libhb/work.c +++ b/libhb/work.c @@ -202,15 +202,15 @@ void hb_display_job_info( hb_job_t * job ) (float) title->rate / (float) title->rate_base, (float) job->vrate / (float) job->vrate_base ); } - if( job->pixel_ratio ) + if( job->anamorphic.mode ) { - hb_log( " + %s anamorphic", job->pixel_ratio == 1 ? "strict" : "loose" ); + hb_log( " + %s anamorphic", job->anamorphic.mode == 1 ? "strict" : "loose" ); hb_log( " + storage dimensions: %d * %d -> %d * %d, crop %d/%d/%d/%d", title->width, title->height, job->width, job->height, job->crop[0], job->crop[1], job->crop[2], job->crop[3] ); - hb_log( " + pixel aspect ratio: %i / %i", job->pixel_aspect_width, job->pixel_aspect_height ); + hb_log( " + pixel aspect ratio: %i / %i", job->anamorphic.par_width, job->anamorphic.par_height ); hb_log( " + display dimensions: %.0f * %i", - (float)( job->width * job->pixel_aspect_width / job->pixel_aspect_height ), job->height ); + (float)( job->width * job->anamorphic.par_width / job->anamorphic.par_height ), job->height ); } else { @@ -365,45 +365,36 @@ static void do_job( hb_job_t * job, int cpu_count ) hb_log( "starting job" ); - if ( job->pixel_ratio == 1 ) - { - /* Correct the geometry of the output movie when using PixelRatio */ - 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 ) + if( job->anamorphic.mode ) { + hb_set_anamorphic_size(job, &job->width, &job->height, &job->anamorphic.par_width, &job->anamorphic.par_height); - /* 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, &job->width, &job->height, &job->pixel_aspect_width, &job->pixel_aspect_height); - } - - if( job->pixel_ratio && job->vcodec == HB_VCODEC_FFMPEG) - { - /* Just to make working with ffmpeg even more fun, - lavc's MPEG-4 encoder can't handle PAR values >= 255, - even though AVRational does. Adjusting downwards - distorts the display aspect slightly, but such is life. */ - while ((job->pixel_aspect_width & ~0xFF) || - (job->pixel_aspect_height & ~0xFF)) + if( job->vcodec == HB_VCODEC_FFMPEG ) { - job->pixel_aspect_width >>= 1; - job->pixel_aspect_height >>= 1; + /* Just to make working with ffmpeg even more fun, + lavc's MPEG-4 encoder can't handle PAR values >= 255, + even though AVRational does. Adjusting downwards + distorts the display aspect slightly, but such is life. */ + while ((job->anamorphic.par_width & ~0xFF) || + (job->anamorphic.par_height & ~0xFF)) + { + job->anamorphic.par_width >>= 1; + job->anamorphic.par_height >>= 1; + } } } - + /* Keep width and height within these boundaries, but ignore for anamorphic. For "loose" anamorphic encodes, this stuff is covered in the pixel_ratio section above. */ - if ( job->maxHeight && ( job->height > job->maxHeight ) && ( !job->pixel_ratio ) ) + if ( job->maxHeight && ( job->height > job->maxHeight ) && ( !job->anamorphic.mode ) ) { 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 ) && ( !job->pixel_ratio ) ) + if ( job->maxWidth && ( job->width > job->maxWidth ) && ( !job->anamorphic.mode ) ) { job->width = job->maxWidth; hb_fix_aspect( job, HB_KEEP_WIDTH ); |