Blame gst-libs/gst/video/video-info.c

Packit 971217
/* GStreamer
Packit 971217
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
Packit 971217
 * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
Packit 971217
 * Copyright (C) 2007 David A. Schleef <ds@schleef.org>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#  include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include <string.h>
Packit 971217
#include <stdio.h>
Packit 971217
Packit 971217
#include "video-info.h"
Packit 971217
#include "video-tile.h"
Packit 971217
Packit 971217
#ifndef GST_DISABLE_GST_DEBUG
Packit 971217
#define GST_CAT_DEFAULT ensure_debug_category()
Packit 971217
static GstDebugCategory *
Packit 971217
ensure_debug_category (void)
Packit 971217
{
Packit 971217
  static gsize cat_gonce = 0;
Packit 971217
Packit 971217
  if (g_once_init_enter (&cat_gonce)) {
Packit 971217
    gsize cat_done;
Packit 971217
Packit 971217
    cat_done = (gsize) _gst_debug_category_new ("video-info", 0,
Packit 971217
        "video-info structure");
Packit 971217
Packit 971217
    g_once_init_leave (&cat_gonce, cat_done);
Packit 971217
  }
Packit 971217
Packit 971217
  return (GstDebugCategory *) cat_gonce;
Packit 971217
}
Packit 971217
#else
Packit 971217
#define ensure_debug_category() /* NOOP */
Packit 971217
#endif /* GST_DISABLE_GST_DEBUG */
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_copy:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 *
Packit 971217
 * Copy a GstVideoInfo structure.
Packit 971217
 *
Packit 971217
 * Returns: a new #GstVideoInfo. free with gst_video_info_free.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
GstVideoInfo *
Packit 971217
gst_video_info_copy (const GstVideoInfo * info)
Packit 971217
{
Packit 971217
  return g_slice_dup (GstVideoInfo, info);
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_free:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 *
Packit 971217
 * Free a GstVideoInfo structure previously allocated with gst_video_info_new()
Packit 971217
 * or gst_video_info_copy().
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
void
Packit 971217
gst_video_info_free (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  g_slice_free (GstVideoInfo, info);
Packit 971217
}
Packit 971217
Packit 971217
G_DEFINE_BOXED_TYPE (GstVideoInfo, gst_video_info,
Packit 971217
    (GBoxedCopyFunc) gst_video_info_copy, (GBoxedFreeFunc) gst_video_info_free);
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_new:
Packit 971217
 *
Packit 971217
 * Allocate a new #GstVideoInfo that is also initialized with
Packit 971217
 * gst_video_info_init().
Packit 971217
 *
Packit 971217
 * Returns: a new #GstVideoInfo. free with gst_video_info_free().
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
GstVideoInfo *
Packit 971217
gst_video_info_new (void)
Packit 971217
{
Packit 971217
  GstVideoInfo *info;
Packit 971217
Packit 971217
  info = g_slice_new (GstVideoInfo);
Packit 971217
  gst_video_info_init (info);
Packit 971217
Packit 971217
  return info;
Packit 971217
}
Packit 971217
Packit 971217
static gboolean fill_planes (GstVideoInfo * info);
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_init:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 *
Packit 971217
 * Initialize @info with default values.
Packit 971217
 */
Packit 971217
void
Packit 971217
gst_video_info_init (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  g_return_if_fail (info != NULL);
Packit 971217
Packit 971217
  memset (info, 0, sizeof (GstVideoInfo));
Packit 971217
Packit 971217
  info->finfo = gst_video_format_get_info (GST_VIDEO_FORMAT_UNKNOWN);
Packit 971217
Packit 971217
  info->views = 1;
Packit 971217
  /* arrange for sensible defaults, e.g. if turned into caps */
Packit 971217
  info->fps_n = 0;
Packit 971217
  info->fps_d = 1;
Packit 971217
  info->par_n = 1;
Packit 971217
  info->par_d = 1;
Packit 971217
  GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
Packit 971217
  GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
Packit 971217
  GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
Packit 971217
}
Packit 971217
Packit 971217
#define MAKE_COLORIMETRY(r,m,t,p) {  \
Packit 971217
  GST_VIDEO_COLOR_RANGE ##r, GST_VIDEO_COLOR_MATRIX_ ##m, \
Packit 971217
  GST_VIDEO_TRANSFER_ ##t, GST_VIDEO_COLOR_PRIMARIES_ ##p }
Packit 971217
Packit 971217
#define DEFAULT_YUV_SD  0
Packit 971217
#define DEFAULT_YUV_HD  1
Packit 971217
#define DEFAULT_RGB     2
Packit 971217
#define DEFAULT_GRAY    3
Packit 971217
#define DEFAULT_UNKNOWN 4
Packit 971217
#define DEFAULT_YUV_UHD 5
Packit 971217
Packit 971217
static const GstVideoColorimetry default_color[] = {
Packit 971217
  MAKE_COLORIMETRY (_16_235, BT601, BT709, SMPTE170M),
Packit 971217
  MAKE_COLORIMETRY (_16_235, BT709, BT709, BT709),
Packit 971217
  MAKE_COLORIMETRY (_0_255, RGB, SRGB, BT709),
Packit 971217
  MAKE_COLORIMETRY (_0_255, BT601, UNKNOWN, UNKNOWN),
Packit 971217
  MAKE_COLORIMETRY (_UNKNOWN, UNKNOWN, UNKNOWN, UNKNOWN),
Packit 971217
  MAKE_COLORIMETRY (_16_235, BT2020, BT2020_12, BT2020),
Packit 971217
};
Packit 971217
Packit 971217
static void
Packit 971217
set_default_colorimetry (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  const GstVideoFormatInfo *finfo = info->finfo;
Packit 971217
Packit 971217
  if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo)) {
Packit 971217
    if (info->height >= 2160) {
Packit 971217
      info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
Packit 971217
      info->colorimetry = default_color[DEFAULT_YUV_UHD];
Packit 971217
    } else if (info->height > 576) {
Packit 971217
      info->chroma_site = GST_VIDEO_CHROMA_SITE_H_COSITED;
Packit 971217
      info->colorimetry = default_color[DEFAULT_YUV_HD];
Packit 971217
    } else {
Packit 971217
      info->chroma_site = GST_VIDEO_CHROMA_SITE_NONE;
Packit 971217
      info->colorimetry = default_color[DEFAULT_YUV_SD];
Packit 971217
    }
Packit 971217
  } else if (GST_VIDEO_FORMAT_INFO_IS_GRAY (finfo)) {
Packit 971217
    info->colorimetry = default_color[DEFAULT_GRAY];
Packit 971217
  } else if (GST_VIDEO_FORMAT_INFO_IS_RGB (finfo)) {
Packit 971217
    info->colorimetry = default_color[DEFAULT_RGB];
Packit 971217
  } else {
Packit 971217
    info->colorimetry = default_color[DEFAULT_UNKNOWN];
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
validate_colorimetry (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  const GstVideoFormatInfo *finfo = info->finfo;
Packit 971217
Packit 971217
  if (!GST_VIDEO_FORMAT_INFO_IS_RGB (finfo) &&
Packit 971217
      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_RGB)
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  if (GST_VIDEO_FORMAT_INFO_IS_YUV (finfo) &&
Packit 971217
      info->colorimetry.matrix == GST_VIDEO_COLOR_MATRIX_UNKNOWN)
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_set_format:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 * @format: the format
Packit 971217
 * @width: a width
Packit 971217
 * @height: a height
Packit 971217
 *
Packit 971217
 * Set the default info for a video frame of @format and @width and @height.
Packit 971217
 *
Packit 971217
 * Note: This initializes @info first, no values are preserved. This function
Packit 971217
 * does not set the offsets correctly for interlaced vertically
Packit 971217
 * subsampled formats.
Packit 971217
 *
Packit 971217
 * Returns: %FALSE if the returned video info is invalid, e.g. because the
Packit 971217
 *   size of a frame can't be represented as a 32 bit integer (Since: 1.12)
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_info_set_format (GstVideoInfo * info, GstVideoFormat format,
Packit 971217
    guint width, guint height)
Packit 971217
{
Packit 971217
  g_return_val_if_fail (info != NULL, FALSE);
Packit 971217
  g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
Packit 971217
Packit 971217
  if (width > G_MAXINT || height > G_MAXINT)
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  gst_video_info_init (info);
Packit 971217
Packit 971217
  info->finfo = gst_video_format_get_info (format);
Packit 971217
  info->width = width;
Packit 971217
  info->height = height;
Packit 971217
  info->views = 1;
Packit 971217
Packit 971217
  set_default_colorimetry (info);
Packit 971217
Packit 971217
  return fill_planes (info);
Packit 971217
}
Packit 971217
Packit 971217
static const gchar *interlace_mode[] = {
Packit 971217
  "progressive",
Packit 971217
  "interleaved",
Packit 971217
  "mixed",
Packit 971217
  "fields"
Packit 971217
};
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_interlace_mode_to_string:
Packit 971217
 * @mode: a #GstVideoInterlaceMode
Packit 971217
 *
Packit 971217
 * Convert @mode to its string representation.
Packit 971217
 *
Packit 971217
 * Returns: @mode as a string or NULL if @mode in invalid.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
const gchar *
Packit 971217
gst_video_interlace_mode_to_string (GstVideoInterlaceMode mode)
Packit 971217
{
Packit 971217
  if (((guint) mode) >= G_N_ELEMENTS (interlace_mode))
Packit 971217
    return NULL;
Packit 971217
Packit 971217
  return interlace_mode[mode];
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_interlace_mode_from_string:
Packit 971217
 * @mode: a mode
Packit 971217
 *
Packit 971217
 * Convert @mode to a #GstVideoInterlaceMode
Packit 971217
 *
Packit 971217
 * Returns: the #GstVideoInterlaceMode of @mode or
Packit 971217
 *    #GST_VIDEO_INTERLACE_MODE_PROGRESSIVE when @mode is not a valid
Packit 971217
 *    string representation for a #GstVideoInterlaceMode.
Packit 971217
 *
Packit 971217
 * Since: 1.6
Packit 971217
 */
Packit 971217
GstVideoInterlaceMode
Packit 971217
gst_video_interlace_mode_from_string (const gchar * mode)
Packit 971217
{
Packit 971217
  gint i;
Packit 971217
  for (i = 0; i < G_N_ELEMENTS (interlace_mode); i++) {
Packit 971217
    if (g_str_equal (interlace_mode[i], mode))
Packit 971217
      return i;
Packit 971217
  }
Packit 971217
  return GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
Packit 971217
}
Packit 971217
Packit 971217
static const gchar *field_order[] = {
Packit 971217
  "unknown",
Packit 971217
  "top-field-first",
Packit 971217
  "bottom-field-first"
Packit 971217
};
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_field_order_to_string:
Packit 971217
 * @order: a #GstVideoFieldOrder
Packit 971217
 *
Packit 971217
 * Convert @order to its string representation.
Packit 971217
 *
Packit 971217
 * Returns: @order as a string or NULL if @order in invalid.
Packit 971217
 *
Packit 971217
 * Since: 1.12
Packit 971217
 */
Packit 971217
const gchar *
Packit 971217
gst_video_field_order_to_string (GstVideoFieldOrder order)
Packit 971217
{
Packit 971217
  if (((guint) order) >= G_N_ELEMENTS (field_order))
Packit 971217
    return NULL;
Packit 971217
Packit 971217
  return field_order[order];
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_field_order_from_string:
Packit 971217
 * @order: a field order
Packit 971217
 *
Packit 971217
 * Convert @order to a #GstVideoFieldOrder
Packit 971217
 *
Packit 971217
 * Returns: the #GstVideoFieldOrder of @order or
Packit 971217
 *    #GST_VIDEO_FIELD_ORDER_UNKNOWN when @order is not a valid
Packit 971217
 *    string representation for a #GstVideoFieldOrder.
Packit 971217
 *
Packit 971217
 * Since: 1.12
Packit 971217
 */
Packit 971217
GstVideoFieldOrder
Packit 971217
gst_video_field_order_from_string (const gchar * order)
Packit 971217
{
Packit 971217
  gint i;
Packit 971217
  for (i = 0; i < G_N_ELEMENTS (field_order); i++) {
Packit 971217
    if (g_str_equal (field_order[i], order))
Packit 971217
      return i;
Packit 971217
  }
Packit 971217
  return GST_VIDEO_FIELD_ORDER_UNKNOWN;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_from_caps:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 * @caps: a #GstCaps
Packit 971217
 *
Packit 971217
 * Parse @caps and update @info.
Packit 971217
 *
Packit 971217
 * Returns: TRUE if @caps could be parsed
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_info_from_caps (GstVideoInfo * info, const GstCaps * caps)
Packit 971217
{
Packit 971217
  GstStructure *structure;
Packit 971217
  const gchar *s;
Packit 971217
  GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
Packit 971217
  gint width = 0, height = 0;
Packit 971217
  gint fps_n, fps_d;
Packit 971217
  gint par_n, par_d;
Packit 971217
  guint multiview_flags;
Packit 971217
Packit 971217
  g_return_val_if_fail (info != NULL, FALSE);
Packit 971217
  g_return_val_if_fail (caps != NULL, FALSE);
Packit 971217
  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
Packit 971217
Packit 971217
  GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
Packit 971217
Packit 971217
  structure = gst_caps_get_structure (caps, 0);
Packit 971217
Packit 971217
  if (gst_structure_has_name (structure, "video/x-raw")) {
Packit 971217
    if (!(s = gst_structure_get_string (structure, "format")))
Packit 971217
      goto no_format;
Packit 971217
Packit 971217
    format = gst_video_format_from_string (s);
Packit 971217
    if (format == GST_VIDEO_FORMAT_UNKNOWN)
Packit 971217
      goto unknown_format;
Packit 971217
Packit 971217
  } else if (g_str_has_prefix (gst_structure_get_name (structure), "video/") ||
Packit 971217
      g_str_has_prefix (gst_structure_get_name (structure), "image/")) {
Packit 971217
    format = GST_VIDEO_FORMAT_ENCODED;
Packit 971217
  } else {
Packit 971217
    goto wrong_name;
Packit 971217
  }
Packit 971217
Packit 971217
  /* width and height are mandatory, except for non-raw-formats */
Packit 971217
  if (!gst_structure_get_int (structure, "width", &width) &&
Packit 971217
      format != GST_VIDEO_FORMAT_ENCODED)
Packit 971217
    goto no_width;
Packit 971217
  if (!gst_structure_get_int (structure, "height", &height) &&
Packit 971217
      format != GST_VIDEO_FORMAT_ENCODED)
Packit 971217
    goto no_height;
Packit 971217
Packit 971217
  gst_video_info_init (info);
Packit 971217
Packit 971217
  info->finfo = gst_video_format_get_info (format);
Packit 971217
  info->width = width;
Packit 971217
  info->height = height;
Packit 971217
Packit 971217
  if (gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d)) {
Packit 971217
    if (fps_n == 0) {
Packit 971217
      /* variable framerate */
Packit 971217
      info->flags |= GST_VIDEO_FLAG_VARIABLE_FPS;
Packit 971217
      /* see if we have a max-framerate */
Packit 971217
      gst_structure_get_fraction (structure, "max-framerate", &fps_n, &fps_d);
Packit 971217
    }
Packit 971217
    info->fps_n = fps_n;
Packit 971217
    info->fps_d = fps_d;
Packit 971217
  } else {
Packit 971217
    /* unspecified is variable framerate */
Packit 971217
    info->fps_n = 0;
Packit 971217
    info->fps_d = 1;
Packit 971217
  }
Packit 971217
Packit 971217
  if (gst_structure_get_fraction (structure, "pixel-aspect-ratio",
Packit 971217
          &par_n, &par_d)) {
Packit 971217
    info->par_n = par_n;
Packit 971217
    info->par_d = par_d;
Packit 971217
  } else {
Packit 971217
    info->par_n = 1;
Packit 971217
    info->par_d = 1;
Packit 971217
  }
Packit 971217
Packit 971217
  if ((s = gst_structure_get_string (structure, "interlace-mode")))
Packit 971217
    info->interlace_mode = gst_video_interlace_mode_from_string (s);
Packit 971217
  else
Packit 971217
    info->interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
Packit 971217
Packit 971217
  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
Packit 971217
      (s = gst_structure_get_string (structure, "field-order"))) {
Packit 971217
    GST_VIDEO_INFO_FIELD_ORDER (info) = gst_video_field_order_from_string (s);
Packit 971217
  } else {
Packit 971217
    GST_VIDEO_INFO_FIELD_ORDER (info) = GST_VIDEO_FIELD_ORDER_UNKNOWN;
Packit 971217
  }
Packit 971217
Packit 971217
  {
Packit 971217
    if ((s = gst_structure_get_string (structure, "multiview-mode")))
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_MODE (info) =
Packit 971217
          gst_video_multiview_mode_from_caps_string (s);
Packit 971217
    else
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_MODE (info) = GST_VIDEO_MULTIVIEW_MODE_NONE;
Packit 971217
Packit 971217
    if (gst_structure_get_flagset (structure, "multiview-flags",
Packit 971217
            &multiview_flags, NULL))
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) = multiview_flags;
Packit 971217
Packit 971217
    if (!gst_structure_get_int (structure, "views", &info->views))
Packit 971217
      info->views = 1;
Packit 971217
Packit 971217
    /* At one point, I tried normalising the half-aspect flag here,
Packit 971217
     * but it behaves weird for GstVideoInfo operations other than
Packit 971217
     * directly converting to/from caps - sometimes causing the
Packit 971217
     * PAR to be doubled/halved too many times */
Packit 971217
  }
Packit 971217
Packit 971217
  if ((s = gst_structure_get_string (structure, "chroma-site")))
Packit 971217
    info->chroma_site = gst_video_chroma_from_string (s);
Packit 971217
  else
Packit 971217
    info->chroma_site = GST_VIDEO_CHROMA_SITE_UNKNOWN;
Packit 971217
Packit 971217
  if ((s = gst_structure_get_string (structure, "colorimetry"))) {
Packit 971217
    if (!gst_video_colorimetry_from_string (&info->colorimetry, s)) {
Packit 971217
      GST_WARNING ("unparsable colorimetry, using default");
Packit 971217
      set_default_colorimetry (info);
Packit 971217
    } else if (!validate_colorimetry (info)) {
Packit 971217
      GST_WARNING ("invalid colorimetry, using default");
Packit 971217
      set_default_colorimetry (info);
Packit 971217
    } else {
Packit 971217
      /* force RGB matrix for RGB formats */
Packit 971217
      if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
Packit 971217
          info->colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
Packit 971217
        GST_WARNING ("invalid matrix %d for RGB format, using RGB",
Packit 971217
            info->colorimetry.matrix);
Packit 971217
        info->colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
Packit 971217
      }
Packit 971217
    }
Packit 971217
  } else {
Packit 971217
    GST_DEBUG ("no colorimetry, using default");
Packit 971217
    set_default_colorimetry (info);
Packit 971217
  }
Packit 971217
Packit 971217
  if (!fill_planes (info))
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
Packit 971217
  /* ERROR */
Packit 971217
wrong_name:
Packit 971217
  {
Packit 971217
    GST_ERROR ("wrong name '%s', expected video/ or image/",
Packit 971217
        gst_structure_get_name (structure));
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_format:
Packit 971217
  {
Packit 971217
    GST_ERROR ("no format given");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
unknown_format:
Packit 971217
  {
Packit 971217
    GST_ERROR ("unknown format '%s' given", s);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_width:
Packit 971217
  {
Packit 971217
    GST_ERROR ("no width property given");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
no_height:
Packit 971217
  {
Packit 971217
    GST_ERROR ("no height property given");
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_is_equal:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 * @other: a #GstVideoInfo
Packit 971217
 *
Packit 971217
 * Compares two #GstVideoInfo and returns whether they are equal or not
Packit 971217
 *
Packit 971217
 * Returns: %TRUE if @info and @other are equal, else %FALSE.
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_info_is_equal (const GstVideoInfo * info, const GstVideoInfo * other)
Packit 971217
{
Packit 971217
  gint i;
Packit 971217
Packit 971217
  if (GST_VIDEO_INFO_FORMAT (info) != GST_VIDEO_INFO_FORMAT (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_INTERLACE_MODE (info) !=
Packit 971217
      GST_VIDEO_INFO_INTERLACE_MODE (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_FLAGS (info) != GST_VIDEO_INFO_FLAGS (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_WIDTH (info) != GST_VIDEO_INFO_WIDTH (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_HEIGHT (info) != GST_VIDEO_INFO_HEIGHT (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_SIZE (info) != GST_VIDEO_INFO_SIZE (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_PAR_N (info) != GST_VIDEO_INFO_PAR_N (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_PAR_D (info) != GST_VIDEO_INFO_PAR_D (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_FPS_N (info) != GST_VIDEO_INFO_FPS_N (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_FPS_D (info) != GST_VIDEO_INFO_FPS_D (other))
Packit 971217
    return FALSE;
Packit 971217
  if (!gst_video_colorimetry_is_equal (&GST_VIDEO_INFO_COLORIMETRY (info),
Packit 971217
          &GST_VIDEO_INFO_COLORIMETRY (other)))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_CHROMA_SITE (info) != GST_VIDEO_INFO_CHROMA_SITE (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) !=
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_MODE (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) !=
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_FLAGS (other))
Packit 971217
    return FALSE;
Packit 971217
  if (GST_VIDEO_INFO_VIEWS (info) != GST_VIDEO_INFO_VIEWS (other))
Packit 971217
    return FALSE;
Packit 971217
Packit 971217
  for (i = 0; i < info->finfo->n_planes; i++) {
Packit 971217
    if (info->stride[i] != other->stride[i])
Packit 971217
      return FALSE;
Packit 971217
    if (info->offset[i] != other->offset[i])
Packit 971217
      return FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_to_caps:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 *
Packit 971217
 * Convert the values of @info into a #GstCaps.
Packit 971217
 *
Packit 971217
 * Returns: a new #GstCaps containing the info of @info.
Packit 971217
 */
Packit 971217
GstCaps *
Packit 971217
gst_video_info_to_caps (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  GstCaps *caps;
Packit 971217
  const gchar *format;
Packit 971217
  gchar *color;
Packit 971217
  gint par_n, par_d;
Packit 971217
  GstVideoColorimetry colorimetry;
Packit 971217
Packit 971217
  g_return_val_if_fail (info != NULL, NULL);
Packit 971217
  g_return_val_if_fail (info->finfo != NULL, NULL);
Packit 971217
  g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, NULL);
Packit 971217
Packit 971217
  format = gst_video_format_to_string (info->finfo->format);
Packit 971217
  g_return_val_if_fail (format != NULL, NULL);
Packit 971217
Packit 971217
  caps = gst_caps_new_simple ("video/x-raw",
Packit 971217
      "format", G_TYPE_STRING, format,
Packit 971217
      "width", G_TYPE_INT, info->width,
Packit 971217
      "height", G_TYPE_INT, info->height, NULL);
Packit 971217
Packit 971217
  par_n = info->par_n;
Packit 971217
  par_d = info->par_d;
Packit 971217
Packit 971217
  gst_caps_set_simple (caps, "interlace-mode", G_TYPE_STRING,
Packit 971217
      gst_video_interlace_mode_to_string (info->interlace_mode), NULL);
Packit 971217
Packit 971217
  if (info->interlace_mode == GST_VIDEO_INTERLACE_MODE_INTERLEAVED &&
Packit 971217
      GST_VIDEO_INFO_FIELD_ORDER (info) != GST_VIDEO_FIELD_ORDER_UNKNOWN) {
Packit 971217
    gst_caps_set_simple (caps, "field-order", G_TYPE_STRING,
Packit 971217
        gst_video_field_order_to_string (GST_VIDEO_INFO_FIELD_ORDER (info)),
Packit 971217
        NULL);
Packit 971217
  }
Packit 971217
Packit 971217
  if (GST_VIDEO_INFO_MULTIVIEW_MODE (info) != GST_VIDEO_MULTIVIEW_MODE_NONE) {
Packit 971217
    const gchar *caps_str = NULL;
Packit 971217
Packit 971217
    /* If the half-aspect flag is set, applying it into the PAR of the
Packit 971217
     * resulting caps now seems safe, and helps with automatic behaviour
Packit 971217
     * in elements that aren't explicitly multiview aware */
Packit 971217
    if (GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &
Packit 971217
        GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT) {
Packit 971217
      GST_VIDEO_INFO_MULTIVIEW_FLAGS (info) &=
Packit 971217
          ~GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
Packit 971217
      switch (GST_VIDEO_INFO_MULTIVIEW_MODE (info)) {
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX:
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED:
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_CHECKERBOARD:
Packit 971217
          par_n *= 2;           /* double the width / half the height */
Packit 971217
          break;
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
Packit 971217
        case GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM:
Packit 971217
          par_d *= 2;           /* half the width / double the height */
Packit 971217
          break;
Packit 971217
        default:
Packit 971217
          break;
Packit 971217
      }
Packit 971217
    }
Packit 971217
Packit 971217
    caps_str =
Packit 971217
        gst_video_multiview_mode_to_caps_string (GST_VIDEO_INFO_MULTIVIEW_MODE
Packit 971217
        (info));
Packit 971217
    if (caps_str != NULL) {
Packit 971217
      gst_caps_set_simple (caps, "multiview-mode", G_TYPE_STRING,
Packit 971217
          caps_str, "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET,
Packit 971217
          GST_VIDEO_INFO_MULTIVIEW_FLAGS (info), GST_FLAG_SET_MASK_EXACT, NULL);
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  gst_caps_set_simple (caps, "pixel-aspect-ratio",
Packit 971217
      GST_TYPE_FRACTION, par_n, par_d, NULL);
Packit 971217
Packit 971217
  if (info->chroma_site != GST_VIDEO_CHROMA_SITE_UNKNOWN)
Packit 971217
    gst_caps_set_simple (caps, "chroma-site", G_TYPE_STRING,
Packit 971217
        gst_video_chroma_to_string (info->chroma_site), NULL);
Packit 971217
Packit 971217
  /* make sure we set the RGB matrix for RGB formats */
Packit 971217
  colorimetry = info->colorimetry;
Packit 971217
  if (GST_VIDEO_FORMAT_INFO_IS_RGB (info->finfo) &&
Packit 971217
      colorimetry.matrix != GST_VIDEO_COLOR_MATRIX_RGB) {
Packit 971217
    GST_WARNING ("invalid matrix %d for RGB format, using RGB",
Packit 971217
        colorimetry.matrix);
Packit 971217
    colorimetry.matrix = GST_VIDEO_COLOR_MATRIX_RGB;
Packit 971217
  }
Packit 971217
  if ((color = gst_video_colorimetry_to_string (&colorimetry))) {
Packit 971217
    gst_caps_set_simple (caps, "colorimetry", G_TYPE_STRING, color, NULL);
Packit 971217
    g_free (color);
Packit 971217
  }
Packit 971217
Packit 971217
  if (info->views > 1)
Packit 971217
    gst_caps_set_simple (caps, "views", G_TYPE_INT, info->views, NULL);
Packit 971217
Packit 971217
  if (info->flags & GST_VIDEO_FLAG_VARIABLE_FPS && info->fps_n != 0) {
Packit 971217
    /* variable fps with a max-framerate */
Packit 971217
    gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, 0, 1,
Packit 971217
        "max-framerate", GST_TYPE_FRACTION, info->fps_n, info->fps_d, NULL);
Packit 971217
  } else {
Packit 971217
    /* no variable fps or no max-framerate */
Packit 971217
    gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION,
Packit 971217
        info->fps_n, info->fps_d, NULL);
Packit 971217
  }
Packit 971217
Packit 971217
  return caps;
Packit 971217
}
Packit 971217
Packit 971217
static gboolean
Packit 971217
fill_planes (GstVideoInfo * info)
Packit 971217
{
Packit 971217
  gsize width, height, cr_h;
Packit 971217
  gint bpp = 0, i;
Packit 971217
Packit 971217
  width = (gsize) info->width;
Packit 971217
  height = (gsize) info->height;
Packit 971217
Packit 971217
  /* Sanity check the resulting frame size for overflows */
Packit 971217
  for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (info); i++)
Packit 971217
    bpp += GST_VIDEO_INFO_COMP_DEPTH (info, i);
Packit 971217
  bpp = GST_ROUND_UP_8 (bpp) / 8;
Packit 971217
  if (bpp > 0 && GST_ROUND_UP_128 ((guint64) width) * ((guint64) height) >=
Packit 971217
      G_MAXUINT / bpp) {
Packit 971217
    GST_ERROR ("Frame size %ux%u would overflow", info->width, info->height);
Packit 971217
    return FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
  switch (info->finfo->format) {
Packit 971217
    case GST_VIDEO_FORMAT_YUY2:
Packit 971217
    case GST_VIDEO_FORMAT_YVYU:
Packit 971217
    case GST_VIDEO_FORMAT_UYVY:
Packit 971217
    case GST_VIDEO_FORMAT_VYUY:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_AYUV:
Packit 971217
    case GST_VIDEO_FORMAT_RGBx:
Packit 971217
    case GST_VIDEO_FORMAT_RGBA:
Packit 971217
    case GST_VIDEO_FORMAT_BGRx:
Packit 971217
    case GST_VIDEO_FORMAT_BGRA:
Packit 971217
    case GST_VIDEO_FORMAT_xRGB:
Packit 971217
    case GST_VIDEO_FORMAT_ARGB:
Packit 971217
    case GST_VIDEO_FORMAT_xBGR:
Packit 971217
    case GST_VIDEO_FORMAT_ABGR:
Packit 971217
    case GST_VIDEO_FORMAT_r210:
Packit 971217
      info->stride[0] = width * 4;
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_RGB16:
Packit 971217
    case GST_VIDEO_FORMAT_BGR16:
Packit 971217
    case GST_VIDEO_FORMAT_RGB15:
Packit 971217
    case GST_VIDEO_FORMAT_BGR15:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_RGB:
Packit 971217
    case GST_VIDEO_FORMAT_BGR:
Packit 971217
    case GST_VIDEO_FORMAT_v308:
Packit 971217
    case GST_VIDEO_FORMAT_IYU2:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 3);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_v210:
Packit 971217
      info->stride[0] = ((width + 47) / 48) * 128;
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_v216:
Packit 971217
      info->stride[0] = GST_ROUND_UP_8 (width * 4);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_GRAY8:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_GRAY16_BE:
Packit 971217
    case GST_VIDEO_FORMAT_GRAY16_LE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_UYVP:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_RGB8P:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = 4;
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->size = info->offset[1] + (4 * 256);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_IYU1:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) +
Packit 971217
          GST_ROUND_UP_4 (width) / 2);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_ARGB64:
Packit 971217
    case GST_VIDEO_FORMAT_AYUV64:
Packit 971217
      info->stride[0] = width * 8;
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_I420:
Packit 971217
    case GST_VIDEO_FORMAT_YV12:        /* same as I420, but plane 1+2 swapped */
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
Packit 971217
      info->size = info->offset[2] + info->stride[2] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_Y41B:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_16 (width) / 4;
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * height;
Packit 971217
      /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */
Packit 971217
      info->size = (info->stride[0] + (GST_ROUND_UP_16 (width) / 2)) * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_Y42B:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_8 (width) / 2;
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * height;
Packit 971217
      /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */
Packit 971217
      info->size = (info->stride[0] + GST_ROUND_UP_8 (width)) * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_Y444:
Packit 971217
    case GST_VIDEO_FORMAT_GBR:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->stride[2] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] * 2;
Packit 971217
      info->size = info->stride[0] * height * 3;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_GBRA:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->stride[2] = info->stride[0];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] * 2;
Packit 971217
      info->offset[3] = info->offset[1] * 3;
Packit 971217
      info->size = info->stride[0] * height * 4;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV12:
Packit 971217
    case GST_VIDEO_FORMAT_NV21:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->size = info->offset[1] + info->stride[0] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV16:
Packit 971217
    case GST_VIDEO_FORMAT_NV61:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->size = info->stride[0] * height * 2;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV24:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->size = info->stride[0] * height + info->stride[1] * height;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_A420:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
Packit 971217
      info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
Packit 971217
      info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_YUV9:
Packit 971217
    case GST_VIDEO_FORMAT_YVU9:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      cr_h = GST_ROUND_UP_4 (height) / 4;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
Packit 971217
      info->size = info->offset[2] + info->stride[2] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_I420_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_I420_10BE:
Packit 971217
    case GST_VIDEO_FORMAT_I420_12LE:
Packit 971217
    case GST_VIDEO_FORMAT_I420_12BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
Packit 971217
      info->size = info->offset[2] + info->stride[2] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_I422_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_I422_10BE:
Packit 971217
    case GST_VIDEO_FORMAT_I422_12LE:
Packit 971217
    case GST_VIDEO_FORMAT_I422_12BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      info->offset[2] = info->offset[1] +
Packit 971217
          info->stride[1] * GST_ROUND_UP_2 (height);
Packit 971217
      info->size = info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_Y444_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_Y444_10BE:
Packit 971217
    case GST_VIDEO_FORMAT_Y444_12LE:
Packit 971217
    case GST_VIDEO_FORMAT_Y444_12BE:
Packit 971217
    case GST_VIDEO_FORMAT_GBR_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_GBR_10BE:
Packit 971217
    case GST_VIDEO_FORMAT_GBR_12LE:
Packit 971217
    case GST_VIDEO_FORMAT_GBR_12BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->stride[2] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] * 2;
Packit 971217
      info->size = info->stride[0] * height * 3;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_GBRA_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_GBRA_10BE:
Packit 971217
    case GST_VIDEO_FORMAT_GBRA_12LE:
Packit 971217
    case GST_VIDEO_FORMAT_GBRA_12BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->stride[2] = info->stride[0];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] * 2;
Packit 971217
      info->offset[3] = info->offset[1] * 3;
Packit 971217
      info->size = info->stride[0] * height * 4;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV12_64Z32:
Packit 971217
      info->stride[0] =
Packit 971217
          GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
Packit 971217
          GST_ROUND_UP_32 (height) / 32);
Packit 971217
      info->stride[1] =
Packit 971217
          GST_VIDEO_TILE_MAKE_STRIDE (GST_ROUND_UP_128 (width) / 64,
Packit 971217
          GST_ROUND_UP_64 (height) / 64);
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = GST_ROUND_UP_128 (width) * GST_ROUND_UP_32 (height);
Packit 971217
      info->size = info->offset[1] +
Packit 971217
          GST_ROUND_UP_128 (width) * GST_ROUND_UP_64 (height) / 2;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_A420_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_A420_10BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->offset[2] = info->offset[1] + info->stride[1] * cr_h;
Packit 971217
      info->offset[3] = info->offset[2] + info->stride[2] * cr_h;
Packit 971217
      info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_A422_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_A422_10BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = GST_ROUND_UP_4 (width);
Packit 971217
      info->stride[2] = info->stride[1];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      info->offset[2] = info->offset[1] +
Packit 971217
          info->stride[1] * GST_ROUND_UP_2 (height);
Packit 971217
      info->offset[3] =
Packit 971217
          info->offset[2] + info->stride[2] * GST_ROUND_UP_2 (height);
Packit 971217
      info->size = info->offset[3] + info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_A444_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_A444_10BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->stride[2] = info->stride[0];
Packit 971217
      info->stride[3] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->offset[2] = info->offset[1] * 2;
Packit 971217
      info->offset[3] = info->offset[1] * 3;
Packit 971217
      info->size = info->stride[0] * height * 4;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_P010_10LE:
Packit 971217
    case GST_VIDEO_FORMAT_P010_10BE:
Packit 971217
      info->stride[0] = GST_ROUND_UP_4 (width * 2);
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      info->size = info->offset[1] + info->stride[0] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_GRAY10_LE32:
Packit 971217
      info->stride[0] = (width + 2) / 3 * 4;
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->size = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV12_10LE32:
Packit 971217
      info->stride[0] = (width + 2) / 3 * 4;
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * GST_ROUND_UP_2 (height);
Packit 971217
      cr_h = GST_ROUND_UP_2 (height) / 2;
Packit 971217
      if (GST_VIDEO_INFO_IS_INTERLACED (info))
Packit 971217
        cr_h = GST_ROUND_UP_2 (cr_h);
Packit 971217
      info->size = info->offset[1] + info->stride[0] * cr_h;
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_NV16_10LE32:
Packit 971217
      info->stride[0] = (width + 2) / 3 * 4;
Packit 971217
      info->stride[1] = info->stride[0];
Packit 971217
      info->offset[0] = 0;
Packit 971217
      info->offset[1] = info->stride[0] * height;
Packit 971217
      info->size = info->stride[0] * height * 2;
Packit 971217
      break;
Packit 971217
Packit 971217
    case GST_VIDEO_FORMAT_ENCODED:
Packit 971217
      break;
Packit 971217
    case GST_VIDEO_FORMAT_UNKNOWN:
Packit 971217
      GST_ERROR ("invalid format");
Packit 971217
      g_warning ("invalid format");
Packit 971217
      return FALSE;
Packit 971217
      break;
Packit 971217
  }
Packit 971217
  return TRUE;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_convert:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 * @src_format: #GstFormat of the @src_value
Packit 971217
 * @src_value: value to convert
Packit 971217
 * @dest_format: #GstFormat of the @dest_value
Packit 971217
 * @dest_value: (out): pointer to destination value
Packit 971217
 *
Packit 971217
 * Converts among various #GstFormat types.  This function handles
Packit 971217
 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT.  For
Packit 971217
 * raw video, GST_FORMAT_DEFAULT corresponds to video frames.  This
Packit 971217
 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
Packit 971217
 *
Packit 971217
 * Returns: TRUE if the conversion was successful.
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_info_convert (GstVideoInfo * info,
Packit 971217
    GstFormat src_format, gint64 src_value,
Packit 971217
    GstFormat dest_format, gint64 * dest_value)
Packit 971217
{
Packit 971217
  gboolean ret = FALSE;
Packit 971217
  int fps_n, fps_d;
Packit 971217
  gsize size;
Packit 971217
Packit 971217
  g_return_val_if_fail (info != NULL, 0);
Packit 971217
  g_return_val_if_fail (info->finfo != NULL, 0);
Packit 971217
  g_return_val_if_fail (info->finfo->format != GST_VIDEO_FORMAT_UNKNOWN, 0);
Packit 971217
  g_return_val_if_fail (info->size > 0, 0);
Packit 971217
Packit 971217
  size = info->size;
Packit 971217
  fps_n = info->fps_n;
Packit 971217
  fps_d = info->fps_d;
Packit 971217
Packit 971217
  GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s",
Packit 971217
      src_value, gst_format_get_name (src_format),
Packit 971217
      gst_format_get_name (dest_format));
Packit 971217
Packit 971217
  if (src_format == dest_format) {
Packit 971217
    *dest_value = src_value;
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  if (src_value == -1) {
Packit 971217
    *dest_value = -1;
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* bytes to frames */
Packit 971217
  if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) {
Packit 971217
    if (size != 0) {
Packit 971217
      *dest_value = gst_util_uint64_scale (src_value, 1, size);
Packit 971217
    } else {
Packit 971217
      GST_ERROR ("blocksize is 0");
Packit 971217
      *dest_value = 0;
Packit 971217
    }
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* frames to bytes */
Packit 971217
  if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) {
Packit 971217
    *dest_value = gst_util_uint64_scale (src_value, size, 1);
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* time to frames */
Packit 971217
  if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) {
Packit 971217
    if (fps_d != 0) {
Packit 971217
      *dest_value = gst_util_uint64_scale (src_value,
Packit 971217
          fps_n, GST_SECOND * fps_d);
Packit 971217
    } else {
Packit 971217
      GST_ERROR ("framerate denominator is 0");
Packit 971217
      *dest_value = 0;
Packit 971217
    }
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* frames to time */
Packit 971217
  if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) {
Packit 971217
    if (fps_n != 0) {
Packit 971217
      *dest_value = gst_util_uint64_scale (src_value,
Packit 971217
          GST_SECOND * fps_d, fps_n);
Packit 971217
    } else {
Packit 971217
      GST_ERROR ("framerate numerator is 0");
Packit 971217
      *dest_value = 0;
Packit 971217
    }
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* time to bytes */
Packit 971217
  if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
Packit 971217
    if (fps_d != 0) {
Packit 971217
      *dest_value = gst_util_uint64_scale (src_value,
Packit 971217
          fps_n * size, GST_SECOND * fps_d);
Packit 971217
    } else {
Packit 971217
      GST_ERROR ("framerate denominator is 0");
Packit 971217
      *dest_value = 0;
Packit 971217
    }
Packit 971217
    ret = TRUE;
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  /* bytes to time */
Packit 971217
  if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
Packit 971217
    if (fps_n != 0 && size != 0) {
Packit 971217
      *dest_value = gst_util_uint64_scale (src_value,
Packit 971217
          GST_SECOND * fps_d, fps_n * size);
Packit 971217
    } else {
Packit 971217
      GST_ERROR ("framerate denominator and/or blocksize is 0");
Packit 971217
      *dest_value = 0;
Packit 971217
    }
Packit 971217
    ret = TRUE;
Packit 971217
  }
Packit 971217
Packit 971217
done:
Packit 971217
Packit 971217
  GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value);
Packit 971217
Packit 971217
  return ret;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * gst_video_info_align:
Packit 971217
 * @info: a #GstVideoInfo
Packit 971217
 * @align: alignment parameters
Packit 971217
 *
Packit 971217
 * Adjust the offset and stride fields in @info so that the padding and
Packit 971217
 * stride alignment in @align is respected.
Packit 971217
 *
Packit 971217
 * Extra padding will be added to the right side when stride alignment padding
Packit 971217
 * is required and @align will be updated with the new padding values.
Packit 971217
 *
Packit 971217
 * Returns: %FALSE if alignment could not be applied, e.g. because the
Packit 971217
 *   size of a frame can't be represented as a 32 bit integer (Since: 1.12)
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
gst_video_info_align (GstVideoInfo * info, GstVideoAlignment * align)
Packit 971217
{
Packit 971217
  const GstVideoFormatInfo *vinfo = info->finfo;
Packit 971217
  gint width, height;
Packit 971217
  gint padded_width, padded_height;
Packit 971217
  gint i, n_planes;
Packit 971217
  gboolean aligned;
Packit 971217
Packit 971217
  width = GST_VIDEO_INFO_WIDTH (info);
Packit 971217
  height = GST_VIDEO_INFO_HEIGHT (info);
Packit 971217
Packit 971217
  GST_LOG ("padding %u-%ux%u-%u", align->padding_top,
Packit 971217
      align->padding_left, align->padding_right, align->padding_bottom);
Packit 971217
Packit 971217
  n_planes = GST_VIDEO_INFO_N_PLANES (info);
Packit 971217
Packit 971217
  if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (vinfo))
Packit 971217
    n_planes--;
Packit 971217
Packit 971217
  /* first make sure the left padding does not cause alignment problems later */
Packit 971217
  do {
Packit 971217
    GST_LOG ("left padding %u", align->padding_left);
Packit 971217
    aligned = TRUE;
Packit 971217
    for (i = 0; i < n_planes; i++) {
Packit 971217
      gint hedge;
Packit 971217
Packit 971217
      /* this is the amout of pixels to add as left padding */
Packit 971217
      hedge = GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, i, align->padding_left);
Packit 971217
      hedge *= GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, i);
Packit 971217
Packit 971217
      GST_LOG ("plane %d, padding %d, alignment %u", i, hedge,
Packit 971217
          align->stride_align[i]);
Packit 971217
      aligned &= (hedge & align->stride_align[i]) == 0;
Packit 971217
    }
Packit 971217
    if (aligned)
Packit 971217
      break;
Packit 971217
Packit 971217
    GST_LOG ("unaligned padding, increasing padding");
Packit 971217
    /* increase padded_width */
Packit 971217
    align->padding_left += align->padding_left & ~(align->padding_left - 1);
Packit 971217
  } while (!aligned);
Packit 971217
Packit 971217
  /* add the padding */
Packit 971217
  padded_width = width + align->padding_left + align->padding_right;
Packit 971217
  padded_height = height + align->padding_top + align->padding_bottom;
Packit 971217
Packit 971217
  do {
Packit 971217
    GST_LOG ("padded dimension %u-%u", padded_width, padded_height);
Packit 971217
Packit 971217
    info->width = padded_width;
Packit 971217
    info->height = padded_height;
Packit 971217
Packit 971217
    if (!fill_planes (info))
Packit 971217
      return FALSE;
Packit 971217
Packit 971217
    /* check alignment */
Packit 971217
    aligned = TRUE;
Packit 971217
    for (i = 0; i < n_planes; i++) {
Packit 971217
      GST_LOG ("plane %d, stride %d, alignment %u", i, info->stride[i],
Packit 971217
          align->stride_align[i]);
Packit 971217
      aligned &= (info->stride[i] & align->stride_align[i]) == 0;
Packit 971217
    }
Packit 971217
    if (aligned)
Packit 971217
      break;
Packit 971217
Packit 971217
    GST_LOG ("unaligned strides, increasing dimension");
Packit 971217
    /* increase padded_width */
Packit 971217
    padded_width += padded_width & ~(padded_width - 1);
Packit 971217
  } while (!aligned);
Packit 971217
Packit 971217
  align->padding_right = padded_width - width - align->padding_left;
Packit 971217
Packit 971217
  info->width = width;
Packit 971217
  info->height = height;
Packit 971217
Packit 971217
  for (i = 0; i < n_planes; i++) {
Packit 971217
    gint vedge, hedge, comp;
Packit 971217
Packit 971217
    /* Find the component for this plane, FIXME, we assume the plane number and
Packit 971217
     * component number is the same for now, for scaling the dimensions this is
Packit 971217
     * currently true for all formats but it might not be when adding new
Packit 971217
     * formats. We might need to add a plane subsamling in the format info to
Packit 971217
     * make this more generic or maybe use a plane -> component mapping. */
Packit 971217
    comp = i;
Packit 971217
Packit 971217
    hedge =
Packit 971217
        GST_VIDEO_FORMAT_INFO_SCALE_WIDTH (vinfo, comp, align->padding_left);
Packit 971217
    vedge =
Packit 971217
        GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (vinfo, comp, align->padding_top);
Packit 971217
Packit 971217
    GST_DEBUG ("plane %d: comp: %d, hedge %d vedge %d align %d stride %d", i,
Packit 971217
        comp, hedge, vedge, align->stride_align[i], info->stride[i]);
Packit 971217
Packit 971217
    info->offset[i] += (vedge * info->stride[i]) +
Packit 971217
        (hedge * GST_VIDEO_FORMAT_INFO_PSTRIDE (vinfo, comp));
Packit 971217
  }
Packit 971217
Packit 971217
  return TRUE;
Packit 971217
}