/* GStreamer
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
 * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#endif

#include <string.h>
#include <stdio.h>

#include "video.h"
#include "gstvideometa.h"

/**
 * SECTION:gstvideo
 * @short_description: Support library for video operations
 *
 * <refsect2>
 * <para>
 * This library contains some helper functions and includes the
 * videosink and videofilter base classes.
 * </para>
 * </refsect2>
 */

/**
 * gst_video_calculate_display_ratio:
 * @dar_n: Numerator of the calculated display_ratio
 * @dar_d: Denominator of the calculated display_ratio
 * @video_width: Width of the video frame in pixels
 * @video_height: Height of the video frame in pixels
 * @video_par_n: Numerator of the pixel aspect ratio of the input video.
 * @video_par_d: Denominator of the pixel aspect ratio of the input video.
 * @display_par_n: Numerator of the pixel aspect ratio of the display device
 * @display_par_d: Denominator of the pixel aspect ratio of the display device
 *
 * Given the Pixel Aspect Ratio and size of an input video frame, and the
 * pixel aspect ratio of the intended display device, calculates the actual
 * display ratio the video will be rendered with.
 *
 * Returns: A boolean indicating success and a calculated Display Ratio in the
 * dar_n and dar_d parameters.
 * The return value is FALSE in the case of integer overflow or other error.
 */
gboolean
gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d,
    guint video_width, guint video_height,
    guint video_par_n, guint video_par_d,
    guint display_par_n, guint display_par_d)
{
  gint num, den;
  gint tmp_n, tmp_d;

  g_return_val_if_fail (dar_n != NULL, FALSE);
  g_return_val_if_fail (dar_d != NULL, FALSE);

  /* Calculate (video_width * video_par_n * display_par_d) /
   * (video_height * video_par_d * display_par_n) */
  if (!gst_util_fraction_multiply (video_width, video_height, video_par_n,
          video_par_d, &tmp_n, &tmp_d))
    goto error_overflow;

  if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n,
          &num, &den))
    goto error_overflow;

  g_return_val_if_fail (num > 0, FALSE);
  g_return_val_if_fail (den > 0, FALSE);

  *dar_n = num;
  *dar_d = den;

  return TRUE;

  /* ERRORS */
error_overflow:
  {
    GST_WARNING ("overflow in multiply");
    return FALSE;
  }
}

/**
 * gst_video_guess_framerate:
 * @duration: Nominal duration of one frame
 * @dest_n: (out) (allow-none): Numerator of the calculated framerate
 * @dest_d: (out) (allow-none): Denominator of the calculated framerate
 *
 * Given the nominal duration of one video frame,
 * this function will check some standard framerates for
 * a close match (within 0.1%) and return one if possible,
 *
 * It will calculate an arbitrary framerate if no close
 * match was found, and return %FALSE.
 *
 * It returns %FALSE if a duration of 0 is passed.
 *
 * Returns: %TRUE if a close "standard" framerate was
 * recognised, and %FALSE otherwise.
 *
 * Since: 1.6
 */
gboolean
gst_video_guess_framerate (GstClockTime duration, gint * dest_n, gint * dest_d)
{
  const int common_den[] = { 1, 2, 3, 4, 1001 };
  int best_n, best_d, gcd;
  guint64 best_error = G_MAXUINT64;
  guint64 a;
  int i;

  if (G_UNLIKELY (duration == 0))
    return FALSE;

  /* Use a limited precision conversion by default for more sensible results,
   * unless the frame duration is absurdly small (high speed cameras?) */
  if (duration > 100000) {
    best_n = 10000;
    best_d = duration / 100000;
  } else {
    best_n = GST_SECOND;
    best_d = duration;
  }

  for (i = 0; i < G_N_ELEMENTS (common_den); i++) {
    gint d = common_den[i];
    gint n = gst_util_uint64_scale_round (d, GST_SECOND, duration);

    /* For NTSC framerates, round to the nearest 1000 fps */
    if (d == 1001) {
      n += 500;
      n -= (n % 1000);
    }

    if (n > 0) {
      /* See what duration the given framerate should be */
      a = gst_util_uint64_scale_int (GST_SECOND, d, n);
      /* Compute absolute error */
      a = (a < duration) ? (duration - a) : (a - duration);
      if (a < 2) {
        /* Really precise - take this option */
        if (dest_n)
          *dest_n = n;
        if (dest_d)
          *dest_d = d;
        return TRUE;
      }
      /* If within 0.1%, remember this denominator */
      if (a * 1000 < duration && a < best_error) {
        best_error = a;
        best_n = n;
        best_d = d;
      }
    }
  }

  /* set results */
  gcd = gst_util_greatest_common_divisor (best_n, best_d);
  if (gcd) {
    best_n /= gcd;
    best_d /= gcd;
  }
  if (dest_n)
    *dest_n = best_n;
  if (dest_d)
    *dest_d = best_d;

  return (best_error != G_MAXUINT64);
}


/**
 * gst_video_alignment_reset:
 * @align: a #GstVideoAlignment
 *
 * Set @align to its default values with no padding and no alignment.
 */
void
gst_video_alignment_reset (GstVideoAlignment * align)
{
  gint i;

  g_return_if_fail (align != NULL);

  align->padding_top = 0;
  align->padding_bottom = 0;
  align->padding_left = 0;
  align->padding_right = 0;
  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++)
    align->stride_align[i] = 0;
}
