Ejemplo n.º 1
0
static gboolean
_calculate_par (GtkGstWidget * widget, GstVideoInfo * info)
{
  gboolean ok;
  gint width, height;
  gint par_n, par_d;
  gint display_par_n, display_par_d;
  guint display_ratio_num, display_ratio_den;

  width = GST_VIDEO_INFO_WIDTH (info);
  height = GST_VIDEO_INFO_HEIGHT (info);

  par_n = GST_VIDEO_INFO_PAR_N (info);
  par_d = GST_VIDEO_INFO_PAR_D (info);

  if (!par_n)
    par_n = 1;

  /* get display's PAR */
  if (widget->priv->par_n != 0 && widget->priv->par_d != 0) {
    display_par_n = widget->priv->par_n;
    display_par_d = widget->priv->par_d;
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }

  ok = gst_video_calculate_display_ratio (&display_ratio_num,
      &display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (!ok)
    return FALSE;

  GST_LOG ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n, display_par_d);

  if (height % display_ratio_den == 0) {
    GST_DEBUG ("keeping video height");
    widget->priv->display_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    widget->priv->display_height = height;
  } else if (width % display_ratio_num == 0) {
    GST_DEBUG ("keeping video width");
    widget->priv->display_width = width;
    widget->priv->display_height = (guint)
        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
  } else {
    GST_DEBUG ("approximating while keeping video height");
    widget->priv->display_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    widget->priv->display_height = height;
  }
  GST_DEBUG ("scaling to %dx%d", widget->priv->display_width,
      widget->priv->display_height);

  return TRUE;
}
Ejemplo n.º 2
0
static void
caps_set(GstCaps *caps, signal_user_data_t *ud)
{
    GstStructure *ss;

    ss = gst_caps_get_structure(caps, 0);
    if (ss)
    {
        gint fps_n, fps_d, width, height;
        guint num, den, par_n, par_d;
        gint disp_par_n, disp_par_d;
        const GValue *par;

        gst_structure_get_fraction(ss, "framerate", &fps_n, &fps_d);
        gst_structure_get_int(ss, "width", &width);
        gst_structure_get_int(ss, "height", &height);
        par = gst_structure_get_value(ss, "pixel-aspect-ratio");
        par_n = gst_value_get_fraction_numerator(par);
        par_d = gst_value_get_fraction_denominator(par);

        ghb_screen_par(ud, &disp_par_n, &disp_par_d);
        gst_video_calculate_display_ratio(
            &num, &den, width, height, par_n, par_d, disp_par_n, disp_par_d);

        if (par_n > par_d)
            width = gst_util_uint64_scale_int(height, num, den);
        else
            height = gst_util_uint64_scale_int(width, den, num);

        if (ghb_dict_get_bool(ud->prefs, "reduce_hd_preview"))
        {
            GdkScreen *ss;
            gint s_w, s_h;

            ss = gdk_screen_get_default();
            s_w = gdk_screen_get_width(ss);
            s_h = gdk_screen_get_height(ss);

            if (width > s_w * 80 / 100)
            {
                width = s_w * 80 / 100;
                height = gst_util_uint64_scale_int(width, den, num);
            }
            if (height > s_h * 80 / 100)
            {
                height = s_h * 80 / 100;
                width = gst_util_uint64_scale_int(height, num, den);
            }
        }

        if (width != ud->preview->width || height != ud->preview->height)
        {
            preview_set_size(ud, width, height);
        }
    }
}
Ejemplo n.º 3
0
static void
caps_set(GstCaps *caps, signal_user_data_t *ud)
{
    GstStructure *ss;

    ss = gst_caps_get_structure(caps, 0);
    if (ss)
    {
        gint fps_n, fps_d, width, height;
        guint num, den, par_n, par_d;
        gint disp_par_n, disp_par_d;
        const GValue *par;

        gst_structure_get_fraction(ss, "framerate", &fps_n, &fps_d);
        gst_structure_get_int(ss, "width", &width);
        gst_structure_get_int(ss, "height", &height);
        par = gst_structure_get_value(ss, "pixel-aspect-ratio");
        par_n = gst_value_get_fraction_numerator(par);
        par_d = gst_value_get_fraction_denominator(par);

        ghb_screen_par(ud, &disp_par_n, &disp_par_d);
        gst_video_calculate_display_ratio(
            &num, &den, width, height, par_n, par_d, disp_par_n, disp_par_d);

        if (par_n > par_d)
            width = gst_util_uint64_scale_int(height, num, den);
        else
            height = gst_util_uint64_scale_int(width, den, num);

        preview_set_size(ud, width, height);
        if (ghb_dict_get_bool(ud->prefs, "reduce_hd_preview"))
        {
            GdkWindow *window;
            gint s_w, s_h;

            window = gtk_widget_get_window(
                        GHB_WIDGET(ud->builder, "preview_window"));
            ghb_monitor_get_size(window, &s_w, &s_h);

            if (s_w > 0 && s_h > 0)
            {
                if (width > s_w * 80 / 100)
                {
                    width = s_w * 80 / 100;
                    height = gst_util_uint64_scale_int(width, den, num);
                }
                if (height > s_h * 80 / 100)
                {
                    height = s_h * 80 / 100;
                    width = gst_util_uint64_scale_int(height, num, den);
                }
            }
        }
    }
}
Ejemplo n.º 4
0
static gboolean
rsn_parsetter_check_caps (RsnParSetter * parset, GstCaps * caps)
{
  GstStructure *s;
  gint width, height;
  gint par_n, par_d;
  guint dar_n, dar_d;
  gboolean ret = FALSE;

  g_mutex_lock (parset->caps_lock);

  if (caps == parset->in_caps_last ||
      gst_caps_is_equal (caps, parset->in_caps_last)) {
    ret = parset->in_caps_was_ok;
    goto out;
  }

  /* Calculate the DAR from the incoming caps, and return TRUE if it matches
   * the required DAR, FALSE if not */
  s = gst_caps_get_structure (caps, 0);
  if (s == NULL)
    goto out;

  if (!gst_structure_get_int (s, "width", &width) ||
      !gst_structure_get_int (s, "height", &height))
    goto out;

  if (!gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d))
    par_n = par_d = 1;

  if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, width, height,
          par_n, par_d, 1, 1))
    goto out;

  GST_DEBUG_OBJECT (parset,
      "Incoming video caps now: w %d h %d PAR %d/%d = DAR %d/%d",
      width, height, par_n, par_d, dar_n, dar_d);

  if (parset->is_widescreen) {
    if (dar_n == 16 && dar_d == 9)
      ret = TRUE;
  } else {
    if (dar_n == 4 && dar_d == 3)
      ret = TRUE;
  }

  gst_caps_replace (&parset->in_caps_last, caps);
  gst_caps_replace (&parset->in_caps_converted, NULL);
  parset->in_caps_was_ok = ret;

out:
  g_mutex_unlock (parset->caps_lock);
  return ret;
}
Ejemplo n.º 5
0
static gboolean
gst_kms_sink_calculate_display_ratio (GstKMSSink * self, GstVideoInfo * vinfo)
{
  guint dar_n, dar_d;
  guint video_width, video_height;
  guint video_par_n, video_par_d;
  guint dpy_par_n, dpy_par_d;

  video_width = GST_VIDEO_INFO_WIDTH (vinfo);
  video_height = GST_VIDEO_INFO_HEIGHT (vinfo);
  video_par_n = GST_VIDEO_INFO_PAR_N (vinfo);
  video_par_d = GST_VIDEO_INFO_PAR_D (vinfo);

  gst_video_calculate_device_ratio (self->hdisplay, self->vdisplay,
      self->mm_width, self->mm_height, &dpy_par_n, &dpy_par_d);

  if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, video_width,
          video_height, video_par_n, video_par_d, dpy_par_n, dpy_par_d))
    return FALSE;

  GST_DEBUG_OBJECT (self, "video calculated display ratio: %d/%d", dar_n,
      dar_d);

  /* now find a width x height that respects this display ratio.
   * prefer those that have one of w/h the same as the incoming video
   * using wd / hd = dar_n / dar_d */

  /* start with same height, because of interlaced video */
  /* check hd / dar_d is an integer scale factor, and scale wd with the PAR */
  if (video_height % dar_d == 0) {
    GST_DEBUG_OBJECT (self, "keeping video height");
    GST_VIDEO_SINK_WIDTH (self) = (guint)
        gst_util_uint64_scale_int (video_height, dar_n, dar_d);
    GST_VIDEO_SINK_HEIGHT (self) = video_height;
  } else if (video_width % dar_n == 0) {
    GST_DEBUG_OBJECT (self, "keeping video width");
    GST_VIDEO_SINK_WIDTH (self) = video_width;
    GST_VIDEO_SINK_HEIGHT (self) = (guint)
        gst_util_uint64_scale_int (video_width, dar_d, dar_n);
  } else {
    GST_DEBUG_OBJECT (self, "approximating while keeping video height");
    GST_VIDEO_SINK_WIDTH (self) = (guint)
        gst_util_uint64_scale_int (video_height, dar_n, dar_d);
    GST_VIDEO_SINK_HEIGHT (self) = video_height;
  }
  GST_DEBUG_OBJECT (self, "scaling to %dx%d", GST_VIDEO_SINK_WIDTH (self),
      GST_VIDEO_SINK_HEIGHT (self));

  return TRUE;
}
Ejemplo n.º 6
0
static void
_mixer_pad_get_output_size (GstGLVideoMixer * mix,
    GstGLVideoMixerPad * mix_pad, gint * width, gint * height)
{
  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
  GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD (mix_pad);
  gint pad_width, pad_height;
  guint dar_n, dar_d;

  /* FIXME: Anything better we can do here? */
  if (!vagg_pad->info.finfo
      || vagg_pad->info.finfo->format == GST_VIDEO_FORMAT_UNKNOWN) {
    GST_DEBUG_OBJECT (mix_pad, "Have no caps yet");
    *width = 0;
    *height = 0;
    return;
  }

  pad_width =
      mix_pad->width <=
      0 ? GST_VIDEO_INFO_WIDTH (&vagg_pad->info) : mix_pad->width;
  pad_height =
      mix_pad->height <=
      0 ? GST_VIDEO_INFO_HEIGHT (&vagg_pad->info) : mix_pad->height;

  gst_video_calculate_display_ratio (&dar_n, &dar_d, pad_width, pad_height,
      GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
      GST_VIDEO_INFO_PAR_D (&vagg_pad->info),
      GST_VIDEO_INFO_PAR_N (&vagg->info), GST_VIDEO_INFO_PAR_D (&vagg->info)
      );
  GST_LOG_OBJECT (mix_pad, "scaling %ux%u by %u/%u (%u/%u / %u/%u)", pad_width,
      pad_height, dar_n, dar_d, GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
      GST_VIDEO_INFO_PAR_D (&vagg_pad->info),
      GST_VIDEO_INFO_PAR_N (&vagg->info), GST_VIDEO_INFO_PAR_D (&vagg->info));

  if (pad_height % dar_n == 0) {
    pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
  } else if (pad_width % dar_d == 0) {
    pad_height = gst_util_uint64_scale_int (pad_width, dar_d, dar_n);
  } else {
    pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
  }

  if (width)
    *width = pad_width;
  if (height)
    *height = pad_height;
}
static void
_mixer_pad_get_output_size (GstCompositor * comp,
                            GstCompositorPad * comp_pad, gint out_par_n, gint out_par_d, gint * width,
                            gint * height)
{
    GstVideoAggregatorPad *vagg_pad = GST_VIDEO_AGGREGATOR_PAD (comp_pad);
    gint pad_width, pad_height;
    guint dar_n, dar_d;

    /* FIXME: Anything better we can do here? */
    if (!vagg_pad->info.finfo
            || vagg_pad->info.finfo->format == GST_VIDEO_FORMAT_UNKNOWN) {
        GST_DEBUG_OBJECT (comp_pad, "Have no caps yet");
        *width = 0;
        *height = 0;
        return;
    }

    pad_width =
        comp_pad->width <=
        0 ? GST_VIDEO_INFO_WIDTH (&vagg_pad->info) : comp_pad->width;
    pad_height =
        comp_pad->height <=
        0 ? GST_VIDEO_INFO_HEIGHT (&vagg_pad->info) : comp_pad->height;

    if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, pad_width, pad_height,
                                            GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
                                            GST_VIDEO_INFO_PAR_D (&vagg_pad->info), out_par_n, out_par_d)) {
        GST_WARNING_OBJECT (comp_pad, "Cannot calculate display aspect ratio");
        *width = *height = 0;
    }
    GST_LOG_OBJECT (comp_pad, "scaling %ux%u by %u/%u (%u/%u / %u/%u)", pad_width,
                    pad_height, dar_n, dar_d, GST_VIDEO_INFO_PAR_N (&vagg_pad->info),
                    GST_VIDEO_INFO_PAR_D (&vagg_pad->info), out_par_n, out_par_d);

    if (pad_height % dar_n == 0) {
        pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
    } else if (pad_width % dar_d == 0) {
        pad_height = gst_util_uint64_scale_int (pad_width, dar_d, dar_n);
    } else {
        pad_width = gst_util_uint64_scale_int (pad_height, dar_n, dar_d);
    }

    *width = pad_width;
    *height = pad_height;
}
Ejemplo n.º 8
0
static gboolean
_calculate_par (GtkGstBaseWidget * widget, GstVideoInfo * info)
{
  gboolean ok;
  gint width, height;
  gint par_n, par_d;
  gint display_par_n, display_par_d;

  width = GST_VIDEO_INFO_WIDTH (info);
  height = GST_VIDEO_INFO_HEIGHT (info);

  par_n = GST_VIDEO_INFO_PAR_N (info);
  par_d = GST_VIDEO_INFO_PAR_D (info);

  if (!par_n)
    par_n = 1;

  /* get display's PAR */
  if (widget->par_n != 0 && widget->par_d != 0) {
    display_par_n = widget->par_n;
    display_par_d = widget->par_d;
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }


  ok = gst_video_calculate_display_ratio (&widget->display_ratio_num,
      &widget->display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (ok) {
    GST_LOG ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n,
        display_par_d);
    return TRUE;
  }

  return FALSE;
}
Ejemplo n.º 9
0
static gboolean gst_imx_egl_viv_sink_gles2_renderer_update_display_ratio(GstImxEglVivSinkGLES2Renderer *renderer, GstVideoInfo *video_info)
{
	/* must be called with lock */

	float display_scale_w, display_scale_h;

	if (renderer->force_aspect_ratio && (renderer->window_width != 0) && (renderer->window_height != 0))
	{
		gint video_par_n, video_par_d, window_par_n, window_par_d;
		float norm_ratio;

		video_par_n = GST_VIDEO_INFO_PAR_N(video_info);
		video_par_d = GST_VIDEO_INFO_PAR_D(video_info);
		window_par_n = 1;
		window_par_d = 1;

		if (!gst_video_calculate_display_ratio(&(renderer->display_ratio_n), &(renderer->display_ratio_d), video_info->width, video_info->height, video_par_n, video_par_d, window_par_n, window_par_d))
		{
			GLES2_RENDERER_UNLOCK(renderer);
			GST_ERROR("could not calculate display ratio");
			return FALSE;
		}

		norm_ratio = (float)(renderer->display_ratio_n) / (float)(renderer->display_ratio_d) * (float)(renderer->window_height) / (float)(renderer->window_width);

		GST_LOG(
			"force aspect ratio: %d  video width/height: %dx%d  video pixel aspect ratio: %d/%d  window pixel aspect ratio: %d/%d  calculated display ratio: %d/%d  window width/height: %dx%d  norm ratio: %f",
			renderer->force_aspect_ratio,
			video_info->width, video_info->height,
			video_par_n, video_par_d,
			window_par_n, window_par_d,
			renderer->display_ratio_n, renderer->display_ratio_d,
			renderer->window_width, renderer->window_height,
			norm_ratio
		);

		if (norm_ratio >= 1.0f)
		{
			display_scale_w = 1.0f;
			display_scale_h = 1.0f / norm_ratio;
		}
		else
		{
			display_scale_w = norm_ratio;
			display_scale_h = 1.0f;
		}
	}
	else
	{
		renderer->display_ratio_n = 1;
		renderer->display_ratio_d = 1;
		display_scale_w = 1.0f;
		display_scale_h = 1.0f;
	}

	if (renderer->frame_rect_uloc != -1)
	{
		GST_LOG(
			"display scale: %f/%f",
			display_scale_w, display_scale_h
		);
		glUniform2f(renderer->frame_rect_uloc, display_scale_w, display_scale_h);
	}

	return TRUE;
}
static GstCaps *
gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
                             GstCaps * caps, GstCaps * othercaps)
{
    GstStructure *ins, *outs;
    const GValue *from_par, *to_par;
    GValue fpar = { 0, }, tpar = {
        0,
    };

    othercaps = gst_caps_truncate (othercaps);
    othercaps = gst_caps_make_writable (othercaps);

    GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT
                      " based on caps %" GST_PTR_FORMAT, othercaps, caps);

    ins = gst_caps_get_structure (caps, 0);
    outs = gst_caps_get_structure (othercaps, 0);

    from_par = gst_structure_get_value (ins, "pixel-aspect-ratio");
    to_par = gst_structure_get_value (outs, "pixel-aspect-ratio");

    /* If we're fixating from the sinkpad we always set the PAR and
     * assume that missing PAR on the sinkpad means 1/1 and
     * missing PAR on the srcpad means undefined
     */
    if (direction == GST_PAD_SINK) {
        if (!from_par) {
            g_value_init (&fpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&fpar, 1, 1);
            from_par = &fpar;
        }
        if (!to_par) {
            g_value_init (&tpar, GST_TYPE_FRACTION_RANGE);
            gst_value_set_fraction_range_full (&tpar, 1, G_MAXINT, G_MAXINT, 1);
            to_par = &tpar;
        }
    } else {
        if (!to_par) {
            g_value_init (&tpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&tpar, 1, 1);
            to_par = &tpar;

            gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1,
                               NULL);
        }
        if (!from_par) {
            g_value_init (&fpar, GST_TYPE_FRACTION);
            gst_value_set_fraction (&fpar, 1, 1);
            from_par = &fpar;
        }
    }

    /* we have both PAR but they might not be fixated */
    {
        gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
        gint w = 0, h = 0;
        gint from_dar_n, from_dar_d;
        gint num, den;

        /* from_par should be fixed */
        g_return_val_if_fail (gst_value_is_fixed (from_par), othercaps);

        from_par_n = gst_value_get_fraction_numerator (from_par);
        from_par_d = gst_value_get_fraction_denominator (from_par);

        gst_structure_get_int (ins, "width", &from_w);
        gst_structure_get_int (ins, "height", &from_h);

        gst_structure_get_int (outs, "width", &w);
        gst_structure_get_int (outs, "height", &h);

        /* if both width and height are already fixed, we can't do anything
         * about it anymore */
        if (w && h) {
            guint n, d;

            GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating",
                              w, h);
            if (!gst_value_is_fixed (to_par)) {
                if (gst_video_calculate_display_ratio (&n, &d, from_w, from_h,
                                                       from_par_n, from_par_d, w, h)) {
                    GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", n, d);
                    if (gst_structure_has_field (outs, "pixel-aspect-ratio"))
                        gst_structure_fixate_field_nearest_fraction (outs,
                                "pixel-aspect-ratio", n, d);
                    else if (n != d)
                        gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                           n, d, NULL);
                }
            }
            goto done;
        }

        /* Calculate input DAR */
        if (!gst_util_fraction_multiply (from_w, from_h, from_par_n, from_par_d,
                                         &from_dar_n, &from_dar_d)) {
            GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                               ("Error calculating the output scaled size - integer overflow"));
            goto done;
        }

        GST_DEBUG_OBJECT (base, "Input DAR is %d/%d", from_dar_n, from_dar_d);

        /* If either width or height are fixed there's not much we
         * can do either except choosing a height or width and PAR
         * that matches the DAR as good as possible
         */
        if (h) {
            GstStructure *tmp;
            gint set_w, set_par_n, set_par_d;

            GST_DEBUG_OBJECT (base, "height is fixed (%d)", h);

            /* If the PAR is fixed too, there's not much to do
             * except choosing the width that is nearest to the
             * width with the same DAR */
            if (gst_value_is_fixed (to_par)) {
                to_par_n = gst_value_get_fraction_numerator (to_par);
                to_par_d = gst_value_get_fraction_denominator (to_par);

                GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);

                if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
                                                 to_par_n, &num, &den)) {
                    GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                       ("Error calculating the output scaled size - integer overflow"));
                    goto done;
                }

                w = (guint) gst_util_uint64_scale_int (h, num, den);
                gst_structure_fixate_field_nearest_int (outs, "width", w);

                goto done;
            }

            /* The PAR is not fixed and it's quite likely that we can set
             * an arbitrary PAR. */

            /* Check if we can keep the input width */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            /* Might have failed but try to keep the DAR nonetheless by
             * adjusting the PAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }

            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            /* Check if the adjusted PAR is accepted */
            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "width", G_TYPE_INT, set_w,
                                       "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
                                       NULL);
                goto done;
            }

            /* Otherwise scale the width to the new PAR and check if the
             * adjusted with is accepted. If all that fails we can't keep
             * the DAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            w = (guint) gst_util_uint64_scale_int (h, num, den);
            gst_structure_fixate_field_nearest_int (outs, "width", w);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);

            goto done;
        } else if (w) {
            GstStructure *tmp;
            gint set_h, set_par_n, set_par_d;

            GST_DEBUG_OBJECT (base, "width is fixed (%d)", w);

            /* If the PAR is fixed too, there's not much to do
             * except choosing the height that is nearest to the
             * height with the same DAR */
            if (gst_value_is_fixed (to_par)) {
                to_par_n = gst_value_get_fraction_numerator (to_par);
                to_par_d = gst_value_get_fraction_denominator (to_par);

                GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d);

                if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d,
                                                 to_par_n, &num, &den)) {
                    GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                       ("Error calculating the output scaled size - integer overflow"));
                    goto done;
                }

                h = (guint) gst_util_uint64_scale_int (w, den, num);
                gst_structure_fixate_field_nearest_int (outs, "height", h);

                goto done;
            }

            /* The PAR is not fixed and it's quite likely that we can set
             * an arbitrary PAR. */

            /* Check if we can keep the input height */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);

            /* Might have failed but try to keep the DAR nonetheless by
             * adjusting the PAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }
            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            /* Check if the adjusted PAR is accepted */
            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "height", G_TYPE_INT, set_h,
                                       "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d,
                                       NULL);
                goto done;
            }

            /* Otherwise scale the height to the new PAR and check if the
             * adjusted with is accepted. If all that fails we can't keep
             * the DAR */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            h = (guint) gst_util_uint64_scale_int (w, den, num);
            gst_structure_fixate_field_nearest_int (outs, "height", h);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);

            goto done;
        } else if (gst_value_is_fixed (to_par)) {
            GstStructure *tmp;
            gint set_h, set_w, f_h, f_w;

            to_par_n = gst_value_get_fraction_numerator (to_par);
            to_par_d = gst_value_get_fraction_denominator (to_par);

            /* Calculate scale factor for the PAR change */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n,
                                             to_par_d, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            /* Try to keep the input height (because of interlacing) */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);

            /* This might have failed but try to scale the width
             * to keep the DAR nonetheless */
            w = (guint) gst_util_uint64_scale_int (set_h, num, den);
            gst_structure_fixate_field_nearest_int (tmp, "width", w);
            gst_structure_get_int (tmp, "width", &set_w);
            gst_structure_free (tmp);

            /* We kept the DAR and the height is nearest to the original height */
            if (set_w == w) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);
                goto done;
            }

            f_h = set_h;
            f_w = set_w;

            /* If the former failed, try to keep the input width at least */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            /* This might have failed but try to scale the width
             * to keep the DAR nonetheless */
            h = (guint) gst_util_uint64_scale_int (set_w, den, num);
            gst_structure_fixate_field_nearest_int (tmp, "height", h);
            gst_structure_get_int (tmp, "height", &set_h);
            gst_structure_free (tmp);

            /* We kept the DAR and the width is nearest to the original width */
            if (set_h == h) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);
                goto done;
            }

            /* If all this failed, keep the height that was nearest to the orignal
             * height and the nearest possible width. This changes the DAR but
             * there's not much else to do here.
             */
            gst_structure_set (outs, "width", G_TYPE_INT, f_w, "height", G_TYPE_INT,
                               f_h, NULL);
            goto done;
        } else {
            GstStructure *tmp;
            gint set_h, set_w, set_par_n, set_par_d, tmp2;

            /* width, height and PAR are not fixed but passthrough is not possible */

            /* First try to keep the height and width as good as possible
             * and scale PAR */
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", from_h);
            gst_structure_get_int (tmp, "height", &set_h);
            gst_structure_fixate_field_nearest_int (tmp, "width", from_w);
            gst_structure_get_int (tmp, "width", &set_w);

            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w,
                                             &to_par_n, &to_par_d)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                gst_structure_free (tmp);
                goto done;
            }

            if (!gst_structure_has_field (tmp, "pixel-aspect-ratio"))
                gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par);
            gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio",
                    to_par_n, to_par_d);
            gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n,
                                        &set_par_d);
            gst_structure_free (tmp);

            if (set_par_n == to_par_n && set_par_d == to_par_d) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, set_h, NULL);

                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* Otherwise try to scale width to keep the DAR with the set
             * PAR and height */
            if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d,
                                             set_par_n, &num, &den)) {
                GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL),
                                   ("Error calculating the output scaled size - integer overflow"));
                goto done;
            }

            w = (guint) gst_util_uint64_scale_int (set_h, num, den);
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "width", w);
            gst_structure_get_int (tmp, "width", &tmp2);
            gst_structure_free (tmp);

            if (tmp2 == w) {
                gst_structure_set (outs, "width", G_TYPE_INT, tmp2, "height",
                                   G_TYPE_INT, set_h, NULL);
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* ... or try the same with the height */
            h = (guint) gst_util_uint64_scale_int (set_w, den, num);
            tmp = gst_structure_copy (outs);
            gst_structure_fixate_field_nearest_int (tmp, "height", h);
            gst_structure_get_int (tmp, "height", &tmp2);
            gst_structure_free (tmp);

            if (tmp2 == h) {
                gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                                   G_TYPE_INT, tmp2, NULL);
                if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                        set_par_n != set_par_d)
                    gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                       set_par_n, set_par_d, NULL);
                goto done;
            }

            /* If all fails we can't keep the DAR and take the nearest values
             * for everything from the first try */
            gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height",
                               G_TYPE_INT, set_h, NULL);
            if (gst_structure_has_field (outs, "pixel-aspect-ratio") ||
                    set_par_n != set_par_d)
                gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION,
                                   set_par_n, set_par_d, NULL);
        }
    }

done:
    GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);

    if (from_par == &fpar)
        g_value_unset (&fpar);
    if (to_par == &tpar)
        g_value_unset (&tpar);

    return othercaps;
}
static gboolean
gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstGLImageSink *glimage_sink;
  gint width;
  gint height;
  gboolean ok;
  gint par_n, par_d;
  gint display_par_n, display_par_d;
  guint display_ratio_num, display_ratio_den;
  GstVideoInfo vinfo;
  GstStructure *structure;
  GstBufferPool *newpool, *oldpool;

  GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  ok = gst_video_info_from_caps (&vinfo, caps);
  if (!ok)
    return FALSE;

  width = GST_VIDEO_INFO_WIDTH (&vinfo);
  height = GST_VIDEO_INFO_HEIGHT (&vinfo);

  if (glimage_sink->tex_id)
    gst_gl_context_del_texture (glimage_sink->context, &glimage_sink->tex_id);
  //FIXME: this texture seems to be never deleted when going to STATE_NULL
  gst_gl_context_gen_texture (glimage_sink->context, &glimage_sink->tex_id,
      GST_VIDEO_INFO_FORMAT (&vinfo), width, height);

  par_n = GST_VIDEO_INFO_PAR_N (&vinfo);
  par_d = GST_VIDEO_INFO_PAR_D (&vinfo);

  if (!par_n)
    par_n = 1;

  /* get display's PAR */
  if (glimage_sink->par_n != 0 && glimage_sink->par_d != 0) {
    display_par_n = glimage_sink->par_n;
    display_par_d = glimage_sink->par_d;
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }

  ok = gst_video_calculate_display_ratio (&display_ratio_num,
      &display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (!ok)
    return FALSE;

  GST_TRACE ("PAR: %u/%u DAR:%u/%u", par_n, par_d, display_par_n,
      display_par_d);

  if (height % display_ratio_den == 0) {
    GST_DEBUG ("keeping video height");
    GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
  } else if (width % display_ratio_num == 0) {
    GST_DEBUG ("keeping video width");
    GST_VIDEO_SINK_WIDTH (glimage_sink) = width;
    GST_VIDEO_SINK_HEIGHT (glimage_sink) = (guint)
        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
  } else {
    GST_DEBUG ("approximating while keeping video height");
    GST_VIDEO_SINK_WIDTH (glimage_sink) = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
  }
  GST_DEBUG ("scaling to %dx%d", GST_VIDEO_SINK_WIDTH (glimage_sink),
      GST_VIDEO_SINK_HEIGHT (glimage_sink));

  glimage_sink->info = vinfo;

  newpool = gst_gl_buffer_pool_new (glimage_sink->context);
  structure = gst_buffer_pool_get_config (newpool);
  gst_buffer_pool_config_set_params (structure, caps, vinfo.size, 2, 0);
  gst_buffer_pool_set_config (newpool, structure);

  oldpool = glimage_sink->pool;
  /* we don't activate the pool yet, this will be done by downstream after it
   * has configured the pool. If downstream does not want our pool we will
   * activate it when we render into it */
  glimage_sink->pool = newpool;

  /* unref the old sink */
  if (oldpool) {
    /* we don't deactivate, some elements might still be using it, it will
     * be deactivated when the last ref is gone */
    gst_object_unref (oldpool);
  }

  return TRUE;
}
Ejemplo n.º 12
0
static void
gst_ffmpegscale_fixate_caps(GstBaseTransform* trans,
                            GstPadDirection direction, GstCaps* caps, GstCaps* othercaps) {
    GstStructure* ins, *outs;
    const GValue* from_par, *to_par;

    g_return_if_fail(gst_caps_is_fixed(caps));

    GST_DEBUG_OBJECT(trans, "trying to fixate othercaps %" GST_PTR_FORMAT
                     " based on caps %" GST_PTR_FORMAT, othercaps, caps);

    ins = gst_caps_get_structure(caps, 0);
    outs = gst_caps_get_structure(othercaps, 0);

    from_par = gst_structure_get_value(ins, "pixel-aspect-ratio");
    to_par = gst_structure_get_value(outs, "pixel-aspect-ratio");

    /* we have both PAR but they might not be fixated */
    if (from_par && to_par) {
        gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d;
        gint count = 0, w = 0, h = 0;
        guint num, den;

        /* from_par should be fixed */
        g_return_if_fail(gst_value_is_fixed(from_par));

        from_par_n = gst_value_get_fraction_numerator(from_par);
        from_par_d = gst_value_get_fraction_denominator(from_par);

        /* fixate the out PAR */
        if (!gst_value_is_fixed(to_par)) {
            GST_DEBUG_OBJECT(trans, "fixating to_par to %dx%d", from_par_n,
                             from_par_d);
            gst_structure_fixate_field_nearest_fraction(outs, "pixel-aspect-ratio",
                    from_par_n, from_par_d);
        }

        to_par_n = gst_value_get_fraction_numerator(to_par);
        to_par_d = gst_value_get_fraction_denominator(to_par);

        /* if both width and height are already fixed, we can't do anything
         * about it anymore */
        if (gst_structure_get_int(outs, "width", &w)) {
            ++count;
        }

        if (gst_structure_get_int(outs, "height", &h)) {
            ++count;
        }

        if (count == 2) {
            GST_DEBUG_OBJECT(trans, "dimensions already set to %dx%d, not fixating",
                             w, h);
            return;
        }

        gst_structure_get_int(ins, "width", &from_w);
        gst_structure_get_int(ins, "height", &from_h);

        if (!gst_video_calculate_display_ratio(&num, &den, from_w, from_h,
                                               from_par_n, from_par_d, to_par_n, to_par_d)) {
            GST_ELEMENT_ERROR(trans, CORE, NEGOTIATION, (NULL),
                              ("Error calculating the output scaled size - integer overflow"));
            return;
        }

        GST_DEBUG_OBJECT(trans,
                         "scaling input with %dx%d and PAR %d/%d to output PAR %d/%d",
                         from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d);
        GST_DEBUG_OBJECT(trans, "resulting output should respect ratio of %d/%d",
                         num, den);

        /* now find a width x height that respects this display ratio.
         * prefer those that have one of w/h the same as the incoming video
         * using wd / hd = num / den */

        /* if one of the output width or height is fixed, we work from there */
        if (h) {
            GST_DEBUG_OBJECT(trans, "height is fixed,scaling width");
            w = (guint) gst_util_uint64_scale_int(h, num, den);
        } else if (w) {
            GST_DEBUG_OBJECT(trans, "width is fixed, scaling height");
            h = (guint) gst_util_uint64_scale_int(w, den, num);
        } else {
            /* none of width or height is fixed, figure out both of them based only on
             * the input width and height */
            /* check hd / den is an integer scale factor, and scale wd with the PAR */
            if (from_h % den == 0) {
                GST_DEBUG_OBJECT(trans, "keeping video height");
                h = from_h;
                w = (guint) gst_util_uint64_scale_int(h, num, den);
            } else if (from_w % num == 0) {
                GST_DEBUG_OBJECT(trans, "keeping video width");
                w = from_w;
                h = (guint) gst_util_uint64_scale_int(w, den, num);
            } else {
                GST_DEBUG_OBJECT(trans, "approximating but keeping video height");
                h = from_h;
                w = (guint) gst_util_uint64_scale_int(h, num, den);
            }
        }

        GST_DEBUG_OBJECT(trans, "scaling to %dx%d", w, h);

        /* now fixate */
        gst_structure_fixate_field_nearest_int(outs, "width", w);
        gst_structure_fixate_field_nearest_int(outs, "height", h);
    } else {
        gint width, height;

        if (gst_structure_get_int(ins, "width", &width)) {
            if (gst_structure_has_field(outs, "width")) {
                gst_structure_fixate_field_nearest_int(outs, "width", width);
            }
        }

        if (gst_structure_get_int(ins, "height", &height)) {
            if (gst_structure_has_field(outs, "height")) {
                gst_structure_fixate_field_nearest_int(outs, "height", height);
            }
        }
    }

    GST_DEBUG_OBJECT(trans, "fixated othercaps to %" GST_PTR_FORMAT, othercaps);
}
Ejemplo n.º 13
0
static GstFlowReturn
gst_eglglessink_render (GstEglGlesSink * eglglessink)
{
  guint dar_n, dar_d;
  gint i;
  gint w, h;

  w = GST_VIDEO_SINK_WIDTH (eglglessink);
  h = GST_VIDEO_SINK_HEIGHT (eglglessink);

  /* If no one has set a display rectangle on us initialize
   * a sane default. According to the docs on the xOverlay
   * interface we are supposed to fill the overlay 100%. We
   * do this trying to take PAR/DAR into account unless the
   * calling party explicitly ask us not to by setting
   * force_aspect_ratio to FALSE.
   */
  if (gst_egl_adaptation_update_surface_dimensions
      (eglglessink->egl_context) || eglglessink->render_region_changed
      || !eglglessink->display_region.w || !eglglessink->display_region.h
      || eglglessink->size_changed) {
    GST_OBJECT_LOCK (eglglessink);

    if (!eglglessink->render_region_user) {
      eglglessink->render_region.x = 0;
      eglglessink->render_region.y = 0;
      eglglessink->render_region.w = eglglessink->egl_context->surface_width;
      eglglessink->render_region.h = eglglessink->egl_context->surface_height;
    }
    eglglessink->render_region_changed = FALSE;
    eglglessink->size_changed = FALSE;

    if (!eglglessink->force_aspect_ratio) {
      eglglessink->display_region.x = 0;
      eglglessink->display_region.y = 0;
      eglglessink->display_region.w = eglglessink->render_region.w;
      eglglessink->display_region.h = eglglessink->render_region.h;
    } else {
      GstVideoRectangle frame;

      frame.x = 0;
      frame.y = 0;

      if (!gst_video_calculate_display_ratio (&dar_n, &dar_d,
              w, h,
              eglglessink->par_n,
              eglglessink->par_d,
              eglglessink->egl_context->pixel_aspect_ratio_n,
              eglglessink->egl_context->pixel_aspect_ratio_d)) {
        GST_WARNING_OBJECT (eglglessink, "Could not compute resulting DAR");
        frame.w = w;
        frame.h = h;
      } else {
        /* Find suitable matching new size acording to dar & par
         * rationale for prefering leaving the height untouched
         * comes from interlacing considerations.
         * XXX: Move this to gstutils?
         */
        if (h % dar_d == 0) {
          frame.w = gst_util_uint64_scale_int (h, dar_n, dar_d);
          frame.h = h;
        } else if (w % dar_n == 0) {
          frame.h = gst_util_uint64_scale_int (w, dar_d, dar_n);
          frame.w = w;
        } else {
          /* Neither width nor height can be precisely scaled.
           * Prefer to leave height untouched. See comment above.
           */
          frame.w = gst_util_uint64_scale_int (h, dar_n, dar_d);
          frame.h = h;
        }
      }

      gst_video_sink_center_rect (frame, eglglessink->render_region,
          &eglglessink->display_region, TRUE);
    }

    glViewport (eglglessink->render_region.x,
        eglglessink->egl_context->surface_height -
        eglglessink->render_region.y -
        eglglessink->render_region.h,
        eglglessink->render_region.w, eglglessink->render_region.h);

    /* Clear the surface once if its content is preserved */
    if (eglglessink->egl_context->buffer_preserved) {
      glClearColor (0.0, 0.0, 0.0, 1.0);
      glClear (GL_COLOR_BUFFER_BIT);
    }

    if (!gst_eglglessink_setup_vbo (eglglessink, FALSE)) {
      GST_OBJECT_UNLOCK (eglglessink);
      GST_ERROR_OBJECT (eglglessink, "VBO setup failed");
      goto HANDLE_ERROR;
    }
    GST_OBJECT_UNLOCK (eglglessink);
  }

  if (!eglglessink->egl_context->buffer_preserved) {
    /* Draw black borders */
    GST_DEBUG_OBJECT (eglglessink, "Drawing black border 1");
    glUseProgram (eglglessink->egl_context->glslprogram[1]);

    glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3,
        GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (4 * sizeof (coord5)));
    if (got_gl_error ("glVertexAttribPointer"))
      goto HANDLE_ERROR;

    glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    if (got_gl_error ("glDrawElements"))
      goto HANDLE_ERROR;

    GST_DEBUG_OBJECT (eglglessink, "Drawing black border 2");

    glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3,
        GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (8 * sizeof (coord5)));
    if (got_gl_error ("glVertexAttribPointer"))
      goto HANDLE_ERROR;

    glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
    if (got_gl_error ("glDrawElements"))
      goto HANDLE_ERROR;
  }

  /* Draw video frame */
  GST_DEBUG_OBJECT (eglglessink, "Drawing video frame");
  glUseProgram (eglglessink->egl_context->glslprogram[0]);

  for (i = 0; i < eglglessink->egl_context->n_textures; i++) {
    glUniform1i (eglglessink->egl_context->tex_loc[0][i], i);
    if (got_gl_error ("glUniform1i"))
      goto HANDLE_ERROR;
  }

  glVertexAttribPointer (eglglessink->egl_context->position_loc[0], 3,
      GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (0 * sizeof (coord5)));
  if (got_gl_error ("glVertexAttribPointer"))
    goto HANDLE_ERROR;

  glVertexAttribPointer (eglglessink->egl_context->texpos_loc[0], 2, GL_FLOAT,
      GL_FALSE, sizeof (coord5), (gpointer) (3 * sizeof (gfloat)));
  if (got_gl_error ("glVertexAttribPointer"))
    goto HANDLE_ERROR;

  glDrawElements (GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
  if (got_gl_error ("glDrawElements"))
    goto HANDLE_ERROR;

  if (!gst_egl_adaptation_swap_buffers (eglglessink->egl_context)) {
    goto HANDLE_ERROR;
  }

  GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame");
  return GST_FLOW_OK;

HANDLE_ERROR:
  GST_ERROR_OBJECT (eglglessink, "Rendering disabled for this frame");

  return GST_FLOW_ERROR;
}
static gboolean
gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstD3DVideoSink *sink;
  GstCaps *sink_caps;
  gint video_width, video_height;
  gint video_par_n, video_par_d;        /* video's PAR */
  gint display_par_n = 1, display_par_d = 1;    /* display's PAR */
  guint num, den;
  GstBufferPool *newpool, *oldpool;
  GstBufferPool *newfbpool, *oldfbpool;
  GstStructure *config;

  GST_DEBUG_OBJECT (bsink, "Caps: %" GST_PTR_FORMAT, caps);
  sink = GST_D3DVIDEOSINK (bsink);

  sink_caps = d3d_supported_caps (sink);

  if (!gst_caps_can_intersect (sink_caps, caps))
    goto incompatible_caps;
  gst_caps_replace (&sink_caps, NULL);

  memset (&sink->info, 0, sizeof (GstVideoInfo));
  if (!gst_video_info_from_caps (&sink->info, caps))
    goto invalid_format;

  sink->format = sink->info.finfo->format;
  video_width = sink->info.width;
  video_height = sink->info.height;
  video_par_n = sink->info.par_n;
  video_par_d = sink->info.par_d;

  GST_DEBUG_OBJECT (bsink, "Set Caps Format: %s",
      gst_video_format_to_string (sink->format));

  /* get aspect ratio from caps if it's present, and
   * convert video width and height to a display width and height
   * using wd / hd = wv / hv * PARv / PARd */

  /* TODO: Get display PAR */

  if (!gst_video_calculate_display_ratio (&num, &den, video_width,
          video_height, video_par_n, video_par_d, display_par_n, display_par_d))
    goto no_disp_ratio;

  GST_DEBUG_OBJECT (sink,
      "video width/height: %dx%d, calculated display ratio: %d/%d format: %u",
      video_width, video_height, num, den, sink->format);

  /* now find a width x height that respects this display ratio.
   * prefer those that have one of w/h the same as the incoming video
   * using wd / hd = num / den
   */

  /* start with same height, because of interlaced video
   * check hd / den is an integer scale factor, and scale wd with the PAR
   */
  if (video_height % den == 0) {
    GST_DEBUG_OBJECT (sink, "keeping video height");
    GST_VIDEO_SINK_WIDTH (sink) = (guint)
        gst_util_uint64_scale_int (video_height, num, den);
    GST_VIDEO_SINK_HEIGHT (sink) = video_height;
  } else if (video_width % num == 0) {
    GST_DEBUG_OBJECT (sink, "keeping video width");
    GST_VIDEO_SINK_WIDTH (sink) = video_width;
    GST_VIDEO_SINK_HEIGHT (sink) = (guint)
        gst_util_uint64_scale_int (video_width, den, num);
  } else {
    GST_DEBUG_OBJECT (sink, "approximating while keeping video height");
    GST_VIDEO_SINK_WIDTH (sink) = (guint)
        gst_util_uint64_scale_int (video_height, num, den);
    GST_VIDEO_SINK_HEIGHT (sink) = video_height;
  }
  GST_DEBUG_OBJECT (sink, "scaling to %dx%d",
      GST_VIDEO_SINK_WIDTH (sink), GST_VIDEO_SINK_HEIGHT (sink));

  if (GST_VIDEO_SINK_WIDTH (sink) <= 0 || GST_VIDEO_SINK_HEIGHT (sink) <= 0)
    goto no_display_size;

  memset (&sink->crop_rect, 0, sizeof (sink->crop_rect));
  sink->crop_rect.w = sink->info.width;
  sink->crop_rect.h = sink->info.height;

  sink->width = video_width;
  sink->height = video_height;

  GST_DEBUG_OBJECT (bsink, "Selected caps: %" GST_PTR_FORMAT, caps);

  if (!d3d_set_render_format (sink))
    goto incompatible_caps;

  /* Create a window (or start using an application-supplied one, then connect the graph */
  d3d_prepare_window (sink);

  newpool = gst_d3dsurface_buffer_pool_new (sink);
  config = gst_buffer_pool_get_config (newpool);
  /* we need at least 2 buffer because we hold on to the last one */
  gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
  if (!gst_buffer_pool_set_config (newpool, config)) {
    gst_object_unref (newpool);
    GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
    return FALSE;
  }

  newfbpool = gst_d3dsurface_buffer_pool_new (sink);
  config = gst_buffer_pool_get_config (newfbpool);
  /* we need at least 2 buffer because we hold on to the last one */
  gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
  /* Fallback pool must use videometa */
  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
  if (!gst_buffer_pool_set_config (newfbpool, config)) {
    gst_object_unref (newfbpool);
    GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
    return FALSE;
  }

  GST_OBJECT_LOCK (sink);
  oldpool = sink->pool;
  sink->pool = newpool;
  oldfbpool = sink->fallback_pool;
  sink->fallback_pool = newfbpool;
  GST_OBJECT_UNLOCK (sink);

  if (oldpool)
    gst_object_unref (oldpool);
  if (oldfbpool) {
    gst_buffer_pool_set_active (oldfbpool, FALSE);
    gst_object_unref (oldfbpool);
  }

  return TRUE;
  /* ERRORS */
incompatible_caps:
  {
    GST_ERROR_OBJECT (sink, "caps incompatible");
    gst_caps_unref (sink_caps);
    return FALSE;
  }
invalid_format:
  {
    GST_DEBUG_OBJECT (sink,
        "Could not locate image format from caps %" GST_PTR_FORMAT, caps);
    return FALSE;
  }
no_disp_ratio:
  {
    GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
        ("Error calculating the output display ratio of the video."));
    return FALSE;
  }
no_display_size:
  {
    GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
        ("Error calculating the output display ratio of the video."));
    return FALSE;
  }
}
Ejemplo n.º 15
0
static gboolean
gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstGLImageSink *glimage_sink;
  gint width;
  gint height;
  gboolean ok;
  gint fps_n, fps_d;
  gint par_n, par_d;
  gint display_par_n, display_par_d;
  guint display_ratio_num, display_ratio_den;
  GstVideoFormat format;
  GstStructure *structure;
  gboolean is_gl;

  GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  structure = gst_caps_get_structure (caps, 0);
  if (gst_structure_has_name (structure, "video/x-raw-gl")) {
    is_gl = TRUE;
    format = GST_VIDEO_FORMAT_UNKNOWN;
    ok = gst_structure_get_int (structure, "width", &width);
    ok &= gst_structure_get_int (structure, "height", &height);
  } else {
    is_gl = FALSE;
    ok = gst_video_format_parse_caps (caps, &format, &width, &height);

    if (!ok)
      return FALSE;

    /* init colorspace conversion if needed */
    ok = gst_gl_display_init_upload (glimage_sink->display, format,
        width, height, width, height);

    if (!ok) {
      GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
          GST_GL_DISPLAY_ERR_MSG (glimage_sink->display), (NULL));
      return FALSE;
    }
  }

  gst_gl_display_set_client_reshape_callback (glimage_sink->display,
      glimage_sink->clientReshapeCallback);

  gst_gl_display_set_client_draw_callback (glimage_sink->display,
      glimage_sink->clientDrawCallback);

  gst_gl_display_set_client_data (glimage_sink->display,
      glimage_sink->client_data);

  ok &= gst_video_parse_caps_framerate (caps, &fps_n, &fps_d);
  ok &= gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d);

  if (!ok)
    return FALSE;

  /* get display's PAR */
  if (glimage_sink->par) {
    display_par_n = gst_value_get_fraction_numerator (glimage_sink->par);
    display_par_d = gst_value_get_fraction_denominator (glimage_sink->par);
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }

  ok = gst_video_calculate_display_ratio (&display_ratio_num,
      &display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (!ok)
    return FALSE;

  if (height % display_ratio_den == 0) {
    GST_DEBUG ("keeping video height");
    glimage_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    glimage_sink->window_height = height;
  } else if (width % display_ratio_num == 0) {
    GST_DEBUG ("keeping video width");
    glimage_sink->window_width = width;
    glimage_sink->window_height = (guint)
        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
  } else {
    GST_DEBUG ("approximating while keeping video height");
    glimage_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    glimage_sink->window_height = height;
  }
  GST_DEBUG ("scaling to %dx%d",
      glimage_sink->window_width, glimage_sink->window_height);

  GST_VIDEO_SINK_WIDTH (glimage_sink) = width;
  GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
  glimage_sink->is_gl = is_gl;
  glimage_sink->width = width;
  glimage_sink->height = height;
  glimage_sink->fps_n = fps_n;
  glimage_sink->fps_d = fps_d;
  glimage_sink->par_n = par_n;
  glimage_sink->par_d = par_d;

  if (!glimage_sink->window_id && !glimage_sink->new_window_id)
    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink));

  return TRUE;
}
Ejemplo n.º 16
0
static gboolean
gst_egl_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstEGLSink *egl_sink;
  gint width;
  gint height;
  gint bufcount;
  gboolean ok;
  gint fps_n, fps_d;
  gint par_n, par_d;
  gint display_par_n, display_par_d;
  guint display_ratio_num, display_ratio_den;
  GstVideoFormat format;
  GstStructure *s;

  GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);

  egl_sink = GST_EGL_SINK (bsink);

  if(egl_sink->set_caps_callback)
    return egl_sink->set_caps_callback(caps, egl_sink->client_data);
  
  s = gst_caps_get_structure (caps, 0);
  if(gst_structure_get_int (s, "num-buffers-required", &bufcount) &&
      bufcount > GST_GL_DISPLAY_MAX_BUFFER_COUNT) {
    GST_WARNING("num-buffers-required %d exceed max eglsink buffer count %d", bufcount, GST_GL_DISPLAY_MAX_BUFFER_COUNT);
    return FALSE;
  }
  
  ok = gst_video_format_parse_caps (caps, &format, &width, &height);
  if (!ok)
    return FALSE;

  ok &= gst_video_parse_caps_framerate (caps, &fps_n, &fps_d);
  ok &= gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d);

  if (!ok)
    return FALSE;

  /* get display's PAR */
  if (egl_sink->par) {
    display_par_n = gst_value_get_fraction_numerator (egl_sink->par);
    display_par_d = gst_value_get_fraction_denominator (egl_sink->par);
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }

  ok = gst_video_calculate_display_ratio (&display_ratio_num,
      &display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (!ok)
    return FALSE;

  if (height % display_ratio_den == 0) {
    GST_DEBUG ("keeping video height");
    egl_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    egl_sink->window_height = height;
  } else if (width % display_ratio_num == 0) {
    GST_DEBUG ("keeping video width");
    egl_sink->window_width = width;
    egl_sink->window_height = (guint)
        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
  } else {
    GST_DEBUG ("approximating while keeping video height");
    egl_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    egl_sink->window_height = height;
  }
  GST_DEBUG ("scaling to %dx%d",
      egl_sink->window_width, egl_sink->window_height);

  GST_VIDEO_SINK_WIDTH (egl_sink) = width;
  GST_VIDEO_SINK_HEIGHT (egl_sink) = height;
  egl_sink->fps_n = fps_n;
  egl_sink->fps_d = fps_d;
  egl_sink->par_n = par_n;
  egl_sink->par_d = par_d;

  if (!egl_sink->window_id && !egl_sink->new_window_id)
    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (egl_sink));

  return TRUE;
}