glupload: Keep input frame mapped as long as needed

When performing a raw upload, we need to keep the raw data mapped as
long as needed.

https://bugzilla.gnome.org/show_bug.cgi?id=752937
This commit is contained in:
Nicolas Dufresne 2015-07-27 16:58:22 -04:00 committed by Tim-Philipp Müller
parent 37cc53d26f
commit 2b2048d601
3 changed files with 61 additions and 16 deletions

View file

@ -1508,22 +1508,26 @@ gst_gl_memory_setup_buffer (GstGLContext * context,
* @valign: a #GstVideoInfo * @valign: a #GstVideoInfo
* @data: a list of per plane data pointers * @data: a list of per plane data pointers
* @textures: (transfer out): a list of #GstGLMemory * @textures: (transfer out): a list of #GstGLMemory
* @user_data: user data for the destroy function
* @notify: A function called each time a memory is freed
* *
* Wraps per plane data pointer in @data into the corresponding entry in * Wraps per plane data pointer in @data into the corresponding entry in
* @textures based on @info and padding from @valign. * @textures based on @info and padding from @valign. Note that the @notify
* will be called as many time as there is planes.
* *
* Returns: whether the memory's were sucessfully created. * Returns: whether the memory's were sucessfully created.
*/ */
gboolean gboolean
gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info, gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info,
GstVideoAlignment * valign, gpointer data[GST_VIDEO_MAX_PLANES], GstVideoAlignment * valign, gpointer data[GST_VIDEO_MAX_PLANES],
GstGLMemory * textures[GST_VIDEO_MAX_PLANES]) GstGLMemory * textures[GST_VIDEO_MAX_PLANES], gpointer user_data,
GDestroyNotify notify)
{ {
gint i; gint i;
for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
textures[i] = (GstGLMemory *) gst_gl_memory_wrapped (context, info, i, textures[i] = (GstGLMemory *) gst_gl_memory_wrapped (context, info, i,
valign, data[i], NULL, NULL); valign, data[i], user_data, notify);
} }
return TRUE; return TRUE;

View file

@ -142,7 +142,9 @@ gboolean gst_gl_memory_setup_wrapped (GstGLContext * context,
GstVideoInfo * info, GstVideoInfo * info,
GstVideoAlignment *valign, GstVideoAlignment *valign,
gpointer data[GST_VIDEO_MAX_PLANES], gpointer data[GST_VIDEO_MAX_PLANES],
GstGLMemory *textures[GST_VIDEO_MAX_PLANES]); GstGLMemory *textures[GST_VIDEO_MAX_PLANES],
gpointer user_data,
GDestroyNotify notify);
gint gst_gl_memory_get_texture_width (GstGLMemory * gl_mem); gint gst_gl_memory_get_texture_width (GstGLMemory * gl_mem);
gint gst_gl_memory_get_texture_height (GstGLMemory * gl_mem); gint gst_gl_memory_get_texture_height (GstGLMemory * gl_mem);

View file

@ -696,12 +696,55 @@ static const UploadMethod _upload_meta_upload = {
&_upload_meta_upload_free &_upload_meta_upload_free
}; };
struct RawUploadFrame
{
gint ref_count;
GstVideoFrame frame;
};
struct RawUpload struct RawUpload
{ {
GstGLUpload *upload; GstGLUpload *upload;
GstVideoFrame in_frame; struct RawUploadFrame *in_frame;
}; };
static struct RawUploadFrame *
_raw_upload_frame_new (struct RawUpload *raw, GstBuffer * buffer)
{
struct RawUploadFrame *frame;
if (!buffer)
return NULL;
frame = g_slice_new (struct RawUploadFrame);
frame->ref_count = 1;
if (!gst_video_frame_map (&frame->frame, &raw->upload->priv->in_info,
buffer, GST_MAP_READ)) {
g_slice_free (struct RawUploadFrame, frame);
return NULL;
}
raw->upload->priv->in_info = frame->frame.info;
return frame;
}
static void
_raw_upload_frame_ref (struct RawUploadFrame *frame)
{
g_atomic_int_inc (&frame->ref_count);
}
static void
_raw_upload_frame_unref (struct RawUploadFrame *frame)
{
if (g_atomic_int_dec_and_test (&frame->ref_count)) {
gst_video_frame_unmap (&frame->frame);
g_slice_free (struct RawUploadFrame, frame);
}
}
static gpointer static gpointer
_raw_data_upload_new (GstGLUpload * upload) _raw_data_upload_new (GstGLUpload * upload)
{ {
@ -738,15 +781,9 @@ _raw_data_upload_accept (gpointer impl, GstBuffer * buffer, GstCaps * in_caps,
if (!gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY)) if (!gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_GL_MEMORY))
return FALSE; return FALSE;
if (buffer) { raw->in_frame = _raw_upload_frame_new (raw, buffer);
if (!gst_video_frame_map (&raw->in_frame, &raw->upload->priv->in_info,
buffer, GST_MAP_READ))
return FALSE;
raw->upload->priv->in_info = raw->in_frame.info; return (raw->in_frame != NULL);
}
return TRUE;
} }
static void static void
@ -772,10 +809,12 @@ _raw_data_upload_perform (gpointer impl, GstBuffer * buffer,
max_planes *= GST_VIDEO_INFO_VIEWS (in_info); max_planes *= GST_VIDEO_INFO_VIEWS (in_info);
gst_gl_memory_setup_wrapped (raw->upload->context, gst_gl_memory_setup_wrapped (raw->upload->context,
&raw->upload->priv->in_info, NULL, raw->in_frame.data, in_tex); &raw->upload->priv->in_info, NULL, raw->in_frame->frame.data, in_tex,
raw->in_frame, (GDestroyNotify) _raw_upload_frame_unref);
*outbuf = gst_buffer_new (); *outbuf = gst_buffer_new ();
for (i = 0; i < max_planes; i++) { for (i = 0; i < max_planes; i++) {
_raw_upload_frame_ref (raw->in_frame);
gst_buffer_append_memory (*outbuf, (GstMemory *) in_tex[i]); gst_buffer_append_memory (*outbuf, (GstMemory *) in_tex[i]);
} }
@ -786,8 +825,8 @@ static void
_raw_data_upload_release (gpointer impl, GstBuffer * buffer) _raw_data_upload_release (gpointer impl, GstBuffer * buffer)
{ {
struct RawUpload *raw = impl; struct RawUpload *raw = impl;
_raw_upload_frame_unref (raw->in_frame);
gst_video_frame_unmap (&raw->in_frame); raw->in_frame = NULL;
} }
static void static void