Ejemplo n.º 1
0
static GstFlowReturn
gst_glimage_sink_prepare (GstBaseSink * bsink, GstBuffer * buf)
{
  GstGLImageSink *glimage_sink;

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  GST_TRACE ("preparing buffer:%p", buf);

  if (GST_VIDEO_SINK_WIDTH (glimage_sink) < 1 ||
      GST_VIDEO_SINK_HEIGHT (glimage_sink) < 1) {
    return GST_FLOW_NOT_NEGOTIATED;
  }

  if (!_ensure_gl_setup (glimage_sink))
    return GST_FLOW_NOT_NEGOTIATED;

  if (!gst_gl_upload_perform_with_buffer (glimage_sink->upload, buf,
          &glimage_sink->next_tex))
    goto upload_failed;

  if (glimage_sink->window_id != glimage_sink->new_window_id) {
    GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

    glimage_sink->window_id = glimage_sink->new_window_id;
    gst_gl_window_set_window_handle (window, glimage_sink->window_id);

    gst_object_unref (window);
  }

  return GST_FLOW_OK;

upload_failed:
  {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", "Failed to upload buffer"), (NULL));
    return GST_FLOW_ERROR;
  }
}
static GstFlowReturn
gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstGLImageSink *glimage_sink;
  guint tex_id;

  GST_TRACE ("rendering buffer:%p", buf);

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  if (GST_VIDEO_SINK_WIDTH (glimage_sink) < 1 ||
      GST_VIDEO_SINK_HEIGHT (glimage_sink) < 1) {
    return GST_FLOW_NOT_NEGOTIATED;
  }

  if (!_ensure_gl_setup (glimage_sink))
    return GST_FLOW_NOT_NEGOTIATED;

  if (!gst_gl_upload_perform_with_buffer (glimage_sink->upload, buf, &tex_id))
    goto upload_failed;

  if (glimage_sink->window_id != glimage_sink->new_window_id) {
    GstGLWindow *window = gst_gl_context_get_window (glimage_sink->context);

    glimage_sink->window_id = glimage_sink->new_window_id;
    gst_gl_window_set_window_handle (window, glimage_sink->window_id);

    gst_object_unref (window);
  }

  GST_TRACE ("redisplay texture:%u of size:%ux%u, window size:%ux%u", tex_id,
      GST_VIDEO_INFO_WIDTH (&glimage_sink->info),
      GST_VIDEO_INFO_HEIGHT (&glimage_sink->info),
      GST_VIDEO_SINK_WIDTH (glimage_sink),
      GST_VIDEO_SINK_HEIGHT (glimage_sink));

  /* Avoid to release the texture while drawing */
  GST_GLIMAGE_SINK_LOCK (glimage_sink);
  glimage_sink->redisplay_texture = tex_id;
  GST_GLIMAGE_SINK_UNLOCK (glimage_sink);

  /* Ask the underlying window to redraw its content */
  if (!gst_glimage_sink_redisplay (glimage_sink))
    goto redisplay_failed;

  GST_TRACE ("post redisplay");

  if (g_atomic_int_get (&glimage_sink->to_quit) != 0) {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    gst_gl_upload_release_buffer (glimage_sink->upload);
    return GST_FLOW_ERROR;
  }

  gst_gl_upload_release_buffer (glimage_sink->upload);
  return GST_FLOW_OK;

/* ERRORS */
redisplay_failed:
  {
    gst_gl_upload_release_buffer (glimage_sink->upload);
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return GST_FLOW_ERROR;
  }

upload_failed:
  {
    GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
        ("%s", "Failed to upload format"), (NULL));
    return FALSE;
  }
}
Ejemplo n.º 3
0
gboolean
gst_gl_mixer_process_textures (GstGLMixer * mix, GstBuffer * outbuf)
{
  guint i;
  GList *walk;
  guint out_tex;
  gboolean res = TRUE;
  guint array_index = 0;
  GstVideoFrame out_frame;
  gboolean out_gl_wrapped = FALSE;
  GstElement *element = GST_ELEMENT (mix);
  GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
  GstGLMixerClass *mix_class = GST_GL_MIXER_GET_CLASS (mix);
  GstGLMixerPrivate *priv = mix->priv;

  GST_TRACE ("Processing buffers");

  if (!gst_video_frame_map (&out_frame, &vagg->info, outbuf,
          GST_MAP_WRITE | GST_MAP_GL)) {
    return FALSE;
  }

  if (gst_is_gl_memory (out_frame.map[0].memory)) {
    out_tex = *(guint *) out_frame.data[0];
  } else {
    GST_INFO ("Output Buffer does not contain correct memory, "
        "attempting to wrap for download");

    out_tex = mix->out_tex_id;;

    if (!mix->download)
      mix->download = gst_gl_download_new (mix->context);

    gst_gl_download_set_format (mix->download, &out_frame.info);
    out_gl_wrapped = TRUE;
  }

  GST_OBJECT_LOCK (mix);
  walk = element->sinkpads;

  i = mix->frames->len;
  g_ptr_array_set_size (mix->frames, element->numsinkpads);
  for (; i < element->numsinkpads; i++)
    mix->frames->pdata[i] = g_slice_new0 (GstGLMixerFrameData);
  while (walk) {
    GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data);
    GstVideoAggregatorPad *vaggpad = walk->data;
    GstGLMixerFrameData *frame;

    frame = g_ptr_array_index (mix->frames, array_index);
    frame->pad = pad;
    frame->texture = 0;

    walk = g_list_next (walk);

    if (vaggpad->buffer != NULL) {
      guint in_tex;

      if (!pad->upload) {
        pad->upload = gst_gl_upload_new (mix->context);

        gst_gl_upload_set_format (pad->upload, &vaggpad->info);
      }

      if (!gst_gl_upload_perform_with_buffer (pad->upload,
              vaggpad->buffer, &in_tex)) {
        ++array_index;
        pad->mapped = FALSE;
        continue;
      }
      pad->mapped = TRUE;

      frame->texture = in_tex;
    }
    ++array_index;
  }

  g_mutex_lock (&priv->gl_resource_lock);
  if (!priv->gl_resource_ready)
    g_cond_wait (&priv->gl_resource_cond, &priv->gl_resource_lock);

  if (!priv->gl_resource_ready) {
    g_mutex_unlock (&priv->gl_resource_lock);
    GST_ERROR_OBJECT (mix,
        "fbo used to render can't be created, do not run process_textures");
    res = FALSE;
    goto out;
  }

  mix_class->process_textures (mix, mix->frames, out_tex);

  g_mutex_unlock (&priv->gl_resource_lock);

  if (out_gl_wrapped) {
    if (!gst_gl_download_perform_with_data (mix->download, out_tex,
            out_frame.data)) {
      GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s",
              "Failed to download video frame"), (NULL));
      res = FALSE;
      goto out;
    }
  }

out:
  i = 0;
  walk = GST_ELEMENT (mix)->sinkpads;
  while (walk) {
    GstGLMixerPad *pad = GST_GL_MIXER_PAD (walk->data);

    if (pad->mapped)
      gst_gl_upload_release_buffer (pad->upload);

    pad->mapped = FALSE;
    walk = g_list_next (walk);
    i++;
  }
  GST_OBJECT_UNLOCK (mix);

  gst_video_frame_unmap (&out_frame);

  return res;
}
Ejemplo n.º 4
0
static GstFlowReturn
stereosplit_chain (GstPad * pad, GstGLStereoSplit * split, GstBuffer * buf)
{
  GstBuffer *uploaded_buffer, *converted_buffer, *left, *right;
  GstBuffer *split_buffer = NULL;
  GstFlowReturn ret;
  gint i, n_planes;

  if (!split->upload)
    _init_upload (split);

  n_planes = GST_VIDEO_INFO_N_PLANES (&split->viewconvert->out_info);

  GST_LOG_OBJECT (split, "chaining buffer %" GST_PTR_FORMAT, buf);

  if (GST_GL_UPLOAD_DONE != gst_gl_upload_perform_with_buffer (split->upload,
          buf, &uploaded_buffer)) {
    gst_buffer_unref (buf);
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to upload buffer"), (NULL));
    return GST_FLOW_ERROR;
  }
  gst_buffer_unref (buf);

  if (!(converted_buffer =
          gst_gl_color_convert_perform (split->convert, uploaded_buffer))) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to convert buffer"), (NULL));
    gst_buffer_unref (uploaded_buffer);
    return GST_FLOW_ERROR;
  }
  gst_buffer_unref (uploaded_buffer);

  if (gst_gl_view_convert_submit_input_buffer (split->viewconvert,
          GST_BUFFER_IS_DISCONT (converted_buffer),
          converted_buffer) != GST_FLOW_OK) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to 3d convert buffer"),
        ("Could not get submit input buffer"));
    return GST_FLOW_ERROR;
  }

  ret = gst_gl_view_convert_get_output (split->viewconvert, &split_buffer);
  if (ret != GST_FLOW_OK) {
    GST_ELEMENT_ERROR (split, RESOURCE, NOT_FOUND, ("%s",
            "Failed to 3d convert buffer"), ("Could not get output buffer"));
    return GST_FLOW_ERROR;
  }
  if (split_buffer == NULL)
    return GST_FLOW_OK;         /* Need another input buffer */

  left = gst_buffer_new ();
  gst_buffer_copy_into (left, buf,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE);

  gst_buffer_add_parent_buffer_meta (left, split_buffer);

  for (i = 0; i < n_planes; i++) {
    GstMemory *mem = gst_buffer_get_memory (split_buffer, i);
    gst_buffer_append_memory (left, mem);
  }

  ret = gst_pad_push (split->left_pad, gst_buffer_ref (left));
  /* Allow unlinked on the first pad - as long as the 2nd isn't unlinked */
  gst_buffer_unref (left);
  if (G_UNLIKELY (ret != GST_FLOW_OK && ret != GST_FLOW_NOT_LINKED)) {
    gst_buffer_unref (split_buffer);
    return ret;
  }

  right = gst_buffer_new ();
  gst_buffer_copy_into (right, buf,
      GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
  GST_BUFFER_FLAG_UNSET (left, GST_VIDEO_BUFFER_FLAG_FIRST_IN_BUNDLE);
  gst_buffer_add_parent_buffer_meta (right, split_buffer);
  for (i = n_planes; i < n_planes * 2; i++) {
    GstMemory *mem = gst_buffer_get_memory (split_buffer, i);
    gst_buffer_append_memory (right, mem);
  }

  ret = gst_pad_push (split->right_pad, gst_buffer_ref (right));
  gst_buffer_unref (right);
  gst_buffer_unref (split_buffer);
  return ret;
}
Ejemplo n.º 5
0
/**
 * gst_gl_filter_filter_texture:
 * @filter: a #GstGLFilter
 * @inbuf: an input buffer
 * @outbuf: an output buffer
 *
 * Perform automatic upload if needed, call filter_texture vfunc and then an
 * automatic download if needed.
 *
 * Returns: whether the transformation succeeded
 */
gboolean
gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf,
    GstBuffer * outbuf)
{
  GstGLFilterClass *filter_class;
  guint in_tex, out_tex;
  GstVideoFrame out_frame;
  gboolean ret, out_gl_mem;
  GstVideoGLTextureUploadMeta *out_tex_upload_meta;

  filter_class = GST_GL_FILTER_GET_CLASS (filter);

  if (!gst_gl_upload_perform_with_buffer (filter->upload, inbuf, &in_tex))
    return FALSE;

  if (!gst_video_frame_map (&out_frame, &filter->out_info, outbuf,
          GST_MAP_WRITE | GST_MAP_GL)) {
    ret = FALSE;
    goto inbuf_error;
  }

  out_gl_mem = gst_is_gl_memory (out_frame.map[0].memory);
  out_tex_upload_meta = gst_buffer_get_video_gl_texture_upload_meta (outbuf);

  if (out_gl_mem) {
    out_tex = *(guint *) out_frame.data[0];
  } else {
    GST_LOG ("Output Buffer does not contain correct memory, "
        "attempting to wrap for download");

    if (!filter->download) {
      filter->download = gst_gl_download_new (filter->context);

      if (!gst_gl_download_init_format (filter->download,
              GST_VIDEO_FRAME_FORMAT (&out_frame),
              GST_VIDEO_FRAME_WIDTH (&out_frame),
              GST_VIDEO_FRAME_HEIGHT (&out_frame))) {
        GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND,
            ("%s", "Failed to init download format"), (NULL));
        ret = FALSE;
        goto error;
      }
    }
    out_tex = filter->out_tex_id;
  }

  GST_DEBUG ("calling filter_texture with textures in:%i out:%i", in_tex,
      out_tex);

  g_assert (filter_class->filter_texture);
  ret = filter_class->filter_texture (filter, in_tex, out_tex);

  if (!out_gl_mem && !out_tex_upload_meta) {
    if (!gst_gl_download_perform_with_data (filter->download, out_tex,
            out_frame.data)) {
      GST_ELEMENT_ERROR (filter, RESOURCE, NOT_FOUND,
          ("%s", "Failed to download video frame"), (NULL));
      ret = FALSE;
      goto error;
    }
  }

error:
  gst_video_frame_unmap (&out_frame);
inbuf_error:
  gst_gl_upload_release_buffer (filter->upload);

  return ret;
}
Ejemplo n.º 6
-1
static GstBuffer *
_default_pad_upload_buffer (GstGLMixer * mix, GstGLMixerFrameData * frame,
                            GstBuffer * buffer)
{
    GstVideoAggregatorPad *vaggpad = GST_VIDEO_AGGREGATOR_PAD (frame->pad);
    GstGLMixerPad *pad = frame->pad;
    GstBuffer *uploaded_buf, *gl_buffer;
    GstCaps *gl_caps;
    GstCapsFeatures *gl_features;
    GstVideoInfo gl_info;
    GstVideoFrame gl_frame;
    GstGLSyncMeta *sync_meta;

    gst_video_info_set_format (&gl_info,
                               GST_VIDEO_FORMAT_RGBA,
                               GST_VIDEO_INFO_WIDTH (&vaggpad->info),
                               GST_VIDEO_INFO_HEIGHT (&vaggpad->info));
    gl_features =
        gst_caps_features_from_string (GST_CAPS_FEATURE_MEMORY_GL_MEMORY);

    gl_caps = gst_video_info_to_caps (&gl_info);
    gst_caps_set_features (gl_caps, 0, gst_caps_features_copy (gl_features));

    if (!pad->upload) {
        GstCaps *in_caps = gst_pad_get_current_caps (GST_PAD (pad));
        GstCaps *upload_caps = gst_caps_copy (in_caps);

        pad->upload = gst_gl_upload_new (mix->context);

        gst_caps_set_features (upload_caps, 0,
                               gst_caps_features_copy (gl_features));
        gst_gl_upload_set_caps (pad->upload, in_caps, upload_caps);

        if (!pad->convert) {
            pad->convert = gst_gl_color_convert_new (mix->context);

            gst_gl_color_convert_set_caps (pad->convert, upload_caps, gl_caps);
        }

        gst_caps_unref (upload_caps);
        gst_caps_unref (in_caps);
    }

    gst_caps_features_free (gl_features);
    gst_caps_unref (gl_caps);

    sync_meta = gst_buffer_get_gl_sync_meta (vaggpad->buffer);
    if (sync_meta)
        gst_gl_sync_meta_wait (sync_meta);

    if (gst_gl_upload_perform_with_buffer (pad->upload,
                                           vaggpad->buffer, &uploaded_buf) != GST_GL_UPLOAD_DONE) {
        return NULL;
    }

    if (!(gl_buffer = gst_gl_color_convert_perform (pad->convert, uploaded_buf))) {
        gst_buffer_unref (uploaded_buf);
        return NULL;
    }

    if (!gst_video_frame_map (&gl_frame, &gl_info, gl_buffer,
                              GST_MAP_READ | GST_MAP_GL)) {
        gst_buffer_unref (uploaded_buf);
        gst_buffer_unref (gl_buffer);
        return NULL;
    }

    frame->texture = *(guint *) gl_frame.data[0];

    gst_buffer_unref (uploaded_buf);
    gst_video_frame_unmap (&gl_frame);

    return gl_buffer;
}