saintdev wrote:As jbrjake has said he has much newer code locally, but feels the need to keep it all to himself
I think I'm finally close to done with this loose anamorphic stuff. Only problem I see right now is that if the sar values are too big, and don't reduce to smaller than 256, then ffmpeg screws up the video stream sar. this makes it play *really* distorted in vlc. Works fine in QuickTime, and the problem is limited to ffmpeg -- xvid and x264 work fine. I can't imagine there are that many people out there who A: care about anamorphic at arbitrary widths, B: only use ffmpeg's encoder, and C: don't use QuickTime.
I've added an optional argument to the -P flag: the modulus you want. So there you go, rhester -- mod 8 away!
For some reason, at least in Darwin, I can't get optional arguments to work with short option names. So -P 16 doesn't work. You've gotta do --loosePixelratio=16 ...not sure what that's about. But the same thing holds for all the flags with optional arguments. Also, for various reasons, this doesn't include raw dimensions. If you want weird numbers that won't compress efficiently, use the old anamorphic function.
Be aware that the way this anamorphic method works can lead to some counter-intuitive results.
For example, I have a movie that, after cropping, is 710*366. If you use the default modulus of 16, loose anamorphic gives you dimensions of 704*368. But if you choose a mod of 8, you get 704*360. Why? Because this method focuses on maintaining the storage aspect ratio. 704/360 is closer to 710/366 than 704/368 is, so when 360 becomes an option (by using mod8), the code will gravitate to that -- even though 368 is more lines. Also, I've set it to tend towards scaling down over scaling up the number of lines.
Anyways, here's the code.
Code: Select all
Index: test/test.c
===================================================================
--- test/test.c (revision 1018)
+++ test/test.c (working copy)
@@ -53,6 +53,8 @@
static int mux = 0;
static int acodec = 0;
static int pixelratio = 0;
+static int loosePixelratio = 0;
+static int modulus = 0;
static int chapter_start = 0;
static int chapter_end = 0;
static int chapter_markers = 0;
@@ -449,8 +451,18 @@
job->deinterlace = deinterlace;
job->grayscale = grayscale;
- job->pixel_ratio = pixelratio;
-
+ if (loosePixelratio)
+ {
+ job->pixel_ratio = 2;
+ if (modulus)
+ {
+ job->modulus = modulus;
+ }
+ }
+ else
+ {
+ job->pixel_ratio = pixelratio;
+ }
/* Add selected filters */
job->filters = hb_list_init();
if( detelecine )
@@ -874,6 +886,10 @@
" <L:R:T:B:SB:MP> (default 1:1:4:4:0:0)\n"
" -g, --grayscale Grayscale encoding\n"
" -p, --pixelratio Store pixel aspect ratio in video stream\n"
+ " -p, --loosePixelratio Store pixel aspect ratio with specified width\n"
+ " <modulus> Takes as optional argument what number you want\n"
+ " the dimensions to divide cleanly by (default 16)\n"
+
"\n"
@@ -949,6 +965,7 @@
{ "detelecine", optional_argument, NULL, '9' },
{ "grayscale", no_argument, NULL, 'g' },
{ "pixelratio", no_argument, NULL, 'p' },
+ { "loosePixelratio", optional_argument, NULL, 'P' },
{ "width", required_argument, NULL, 'w' },
{ "height", required_argument, NULL, 'l' },
{ "crop", required_argument, NULL, 'n' },
@@ -973,7 +990,7 @@
int c;
c = getopt_long( argc, argv,
- "hvuC:f:4i:o:t:Lc:ma:6:s:UFN:e:E:2d789gpw:l:n:b:q:S:B:r:R:Qx:TY:X:",
+ "hvuC:f:4i:o:t:Lc:ma:6:s:UFN:e:E:2d789gpP::w:l:n:b:q:S:B:r:R:Qx:TY:X:",
long_options, &option_index );
if( c < 0 )
{
@@ -1115,6 +1132,13 @@
case 'p':
pixelratio = 1;
break;
+ case 'P':
+ loosePixelratio = 1;
+ if( optarg != NULL )
+ {
+ modulus = atoi( optarg );
+ }
+ break;
case 'e':
if( !strcasecmp( optarg, "ffmpeg" ) )
{
Index: libhb/hb.c
===================================================================
--- libhb/hb.c (revision 1018)
+++ libhb/hb.c (working copy)
@@ -427,6 +427,156 @@
}
/**
+ * 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.
Index: libhb/hb.h
===================================================================
--- libhb/hb.h (revision 1018)
+++ libhb/hb.h (working copy)
@@ -78,6 +78,7 @@
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 * );
Index: libhb/work.c
===================================================================
--- libhb/work.c (revision 1018)
+++ libhb/work.c (working copy)
@@ -128,16 +128,27 @@
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 )
+ {
- /* Keep width and height within these boundaries */
- if (job->maxHeight && (job->height > job->maxHeight) )
+ /* 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,
+ 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 );
Index: libhb/common.h
===================================================================
--- libhb/common.h (revision 1018)
+++ libhb/common.h (working copy)
@@ -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 @@
int pixel_ratio;
int pixel_aspect_width;
int pixel_aspect_height;
+ int modulus;
int maxWidth;
int maxHeight;