summaryrefslogtreecommitdiffstats
path: root/libhb
diff options
context:
space:
mode:
Diffstat (limited to 'libhb')
-rw-r--r--libhb/common.h16
-rw-r--r--libhb/encavcodec.c8
-rw-r--r--libhb/enctheora.c6
-rw-r--r--libhb/encx264.c6
-rw-r--r--libhb/encxvid.c6
-rw-r--r--libhb/hb.c180
-rw-r--r--libhb/muxavi.c8
-rw-r--r--libhb/muxmkv.c4
-rw-r--r--libhb/muxmp4.c6
-rw-r--r--libhb/scan.c8
-rw-r--r--libhb/work.c49
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 );