+/**
+ * Calculates job width and height for anamorphic content,
+ *
+ * @param job Handle to hb_job_t
+ * @param output_width Pointer to returned storage width
+ * @param output_height Pointer to returned storage height
+ * @param output_par_width Pointer to returned pixel width
+ @ param output_par_height Pointer to returned pixel height
+ */
+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;
+ 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)
+ {
+ // convert aspect to a scaled integer so we can test for 16:9 & 4:3
+ // aspect ratios ignoring insignificant differences in the LSBs of
+ // the floating point representation.
+ int iaspect = aspect * 9.;
+
+ /* Handle ITU PARs */
+ if (title->height == 480)
+ {
+ /* It's NTSC */
+ if (iaspect == 16)
+ {
+ /* It's widescreen */
+ pixel_aspect_width = 40;
+ pixel_aspect_height = 33;
+ }
+ else if (iaspect == 12)
+ {
+ /* It's 4:3 */
+ pixel_aspect_width = 10;
+ pixel_aspect_height = 11;
+ }
+ }
+ else if (title->height == 576)
+ {
+ /* It's PAL */
+ if(iaspect == 16)
+ {
+ /* It's widescreen */
+ pixel_aspect_width = 16;
+ pixel_aspect_height = 11;
+ }
+ else if (iaspect == 12)
+ {
+ /* It's 4:3 */
+ pixel_aspect_width = 12;
+ pixel_aspect_height = 11;
+ }
+ }
+ }
+
+ /* Figure out what dimensions 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;
+
+ /* 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,
+ pixel_aspect_width, 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.
+ * @param pixels Maximum desired pixel count.
+ */
+void hb_set_size( hb_job_t * job, double aspect, int pixels )
+{
+ hb_title_t * title = job->title;
+
+ int croppedWidth = title->width - title->crop[2] - title->crop[3];
+ int croppedHeight = title->height - title->crop[0] - title->crop[1];
+ double croppedAspect = title->aspect * title->height * croppedWidth /
+ croppedHeight / title->width;
+ int addCrop;
+ int i, w, h;
+
+ if( aspect <= 0 )
+ {
+ /* Keep the best possible aspect ratio */
+ aspect = croppedAspect;
+ }
+
+ /* Crop if necessary to obtain the desired ratio */
+ memcpy( job->crop, title->crop, 4 * sizeof( int ) );
+ if( aspect < croppedAspect )
+ {
+ /* Need to crop on the left and right */
+ addCrop = croppedWidth - aspect * croppedHeight * title->width /
+ title->aspect / title->height;
+ if( addCrop & 3 )
+ {
+ addCrop = ( addCrop + 1 ) / 2;
+ job->crop[2] += addCrop;
+ job->crop[3] += addCrop;
+ }
+ else if( addCrop & 2 )
+ {
+ addCrop /= 2;
+ job->crop[2] += addCrop - 1;
+ job->crop[3] += addCrop + 1;
+ }
+ else
+ {
+ addCrop /= 2;
+ job->crop[2] += addCrop;
+ job->crop[3] += addCrop;
+ }
+ }
+ else if( aspect > croppedAspect )
+ {
+ /* Need to crop on the top and bottom */
+ addCrop = croppedHeight - croppedWidth * title->aspect *
+ title->height / aspect / title->width;
+ if( addCrop & 3 )
+ {
+ addCrop = ( addCrop + 1 ) / 2;
+ job->crop[0] += addCrop;
+ job->crop[1] += addCrop;
+ }
+ else if( addCrop & 2 )
+ {
+ addCrop /= 2;
+ job->crop[0] += addCrop - 1;
+ job->crop[1] += addCrop + 1;
+ }
+ else
+ {
+ addCrop /= 2;
+ job->crop[0] += addCrop;
+ job->crop[1] += addCrop;
+ }
+ }
+
+ /* Compute a resolution from the number of pixels and aspect */
+ for( i = 0;; i++ )
+ {
+ w = 16 * i;
+ h = MULTIPLE_16( (int)( (double)w / aspect ) );
+ if( w * h > pixels )
+ {
+ break;
+ }
+ }
+ i--;
+ job->width = 16 * i;
+ job->height = MULTIPLE_16( (int)( (double)job->width / aspect ) );
+}
+
+/**
+ * Returns the number of jobs in the queue.
+ * @param h Handle to hb_handle_t.
+ * @return Number of jobs.
+ */