video: Improve video frame map/unmap

Install defaul map/unmap function on the metadata and really call the functions
instead of always calling a default implementation.
Rework some bits so that we don't have to mess with the GstMapInfo information
(adding the offset), instead pass the adjusted data pointer from the map function.
This commit is contained in:
Wim Taymans 2012-02-23 16:28:29 +01:00
parent f552d8f0c0
commit e32e8f6c52
3 changed files with 88 additions and 96 deletions

View file

@ -91,6 +91,71 @@ gst_buffer_get_video_meta_id (GstBuffer * buffer, gint id)
return NULL; return NULL;
} }
static gboolean
default_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
gpointer * data, gint * stride, GstMapFlags flags)
{
guint n, i;
guint offset;
GstBuffer *buffer = meta->buffer;
if ((n = gst_buffer_n_memory (buffer)) == 0)
goto no_memory;
offset = meta->offset[plane];
*stride = meta->stride[plane];
/* find the memory block for this plane, this is the memory block containing
* the plane offset. @offset will be updated with the offset inside the memory
* block where the plane starts. */
for (i = 0; i < n; i++) {
GstMemory *mem = NULL;
gsize size;
mem = gst_buffer_get_memory (buffer, i);
size = gst_memory_get_sizes (mem, NULL, NULL);
if (offset < size) {
GstMemory *mapped;
if (!(mapped = gst_memory_make_mapped (mem, info, flags)))
goto cannot_map;
/* buffer is writable when WRITE map is requested, we checked this in
* _map * */
if (mapped != mem && (flags & GST_MAP_WRITE))
gst_buffer_replace_memory (buffer, i, gst_memory_ref (mapped));
*data = (guint8 *) info->data + offset;
return TRUE;
}
offset -= size;
gst_memory_unref (mem);
}
GST_DEBUG ("no memory found for offset %u", meta->offset[plane]);
return FALSE;
/* ERRORS */
no_memory:
{
GST_DEBUG ("no memory");
return FALSE;
}
cannot_map:
{
GST_DEBUG ("cannot map memory");
return FALSE;
}
}
static gboolean
default_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
{
gst_memory_unmap (info->memory, info);
gst_memory_unref (info->memory);
return TRUE;
}
/** /**
* gst_buffer_add_video_meta: * gst_buffer_add_video_meta:
* @buffer: a #GstBuffer * @buffer: a #GstBuffer
@ -161,59 +226,18 @@ gst_buffer_add_video_meta_full (GstBuffer * buffer, GstVideoFlags flags,
meta->offset[i] = offset[i]; meta->offset[i] = offset[i];
meta->stride[i] = stride[i]; meta->stride[i] = stride[i];
} }
meta->map = default_map;
meta->unmap = default_unmap;
return meta; return meta;
} }
static gboolean
map_mem_for_offset (GstBuffer * buffer, guint * offset, GstMapInfo * info,
GstMapFlags flags)
{
guint n, i;
if ((n = gst_buffer_n_memory (buffer)) == 0)
goto no_memory;
for (i = 0; i < n; i++) {
GstMemory *mem = NULL;
gsize size;
mem = gst_buffer_get_memory (buffer, i);
size = gst_memory_get_sizes (mem, NULL, NULL);
if (*offset < size) {
GstMemory *mapped;
if (!(mapped = gst_memory_make_mapped (mem, info, flags)))
goto cannot_map;
if (mapped != mem && (flags & GST_MAP_WRITE))
gst_buffer_replace_memory (buffer, i, gst_memory_ref (mapped));
break;
}
*offset -= size;
gst_memory_unref (mem);
}
return TRUE;
/* ERRORS */
no_memory:
{
GST_DEBUG ("no memory");
return FALSE;
}
cannot_map:
{
GST_DEBUG ("cannot map memory");
return FALSE;
}
}
/** /**
* gst_video_meta_map: * gst_video_meta_map:
* @meta: a #GstVideoMeta * @meta: a #GstVideoMeta
* @plane: a plane * @plane: a plane
* @info: a #GstMapInfo * @info: a #GstMapInfo
* @stride: result stride * @offset: the offset of where the plane starts in @info
* @flags: @GstMapFlags * @flags: @GstMapFlags
* *
* Map the video plane with index @plane in @meta and return a pointer to the * Map the video plane with index @plane in @meta and return a pointer to the
@ -223,36 +247,19 @@ cannot_map:
*/ */
gboolean gboolean
gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info, gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
gint * stride, GstMapFlags flags) gpointer * data, gint * stride, GstMapFlags flags)
{ {
guint offset;
gboolean write, res;
GstBuffer *buffer;
g_return_val_if_fail (meta != NULL, FALSE); g_return_val_if_fail (meta != NULL, FALSE);
g_return_val_if_fail (meta->map != NULL, FALSE);
g_return_val_if_fail (plane < meta->n_planes, FALSE); g_return_val_if_fail (plane < meta->n_planes, FALSE);
g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (info != NULL, FALSE);
g_return_val_if_fail (data != NULL, FALSE);
g_return_val_if_fail (stride != NULL, FALSE); g_return_val_if_fail (stride != NULL, FALSE);
g_return_val_if_fail (meta->buffer != NULL, FALSE);
g_return_val_if_fail (!(flags & GST_MAP_WRITE)
|| gst_buffer_is_writable (meta->buffer), FALSE);
buffer = meta->buffer; return meta->map (meta, plane, info, data, stride, flags);
g_return_val_if_fail (buffer != NULL, FALSE);
write = (flags & GST_MAP_WRITE) != 0;
g_return_val_if_fail (!write || gst_buffer_is_writable (buffer), FALSE);
offset = meta->offset[plane];
*stride = meta->stride[plane];
/* find the memory block for this plane, this is the memory block containing
* the plane offset */
res = map_mem_for_offset (buffer, &offset, info, flags);
if (G_LIKELY (res)) {
/* move to the right offset inside the block */
info->data += offset;
info->size -= offset;
info->maxsize -= offset;
}
return res;
} }
/** /**
@ -268,27 +275,12 @@ gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
gboolean gboolean
gst_video_meta_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info) gst_video_meta_unmap (GstVideoMeta * meta, guint plane, GstMapInfo * info)
{ {
guint offset;
GstBuffer *buffer;
g_return_val_if_fail (meta != NULL, FALSE); g_return_val_if_fail (meta != NULL, FALSE);
g_return_val_if_fail (meta->unmap != NULL, FALSE);
g_return_val_if_fail (plane < meta->n_planes, FALSE); g_return_val_if_fail (plane < meta->n_planes, FALSE);
g_return_val_if_fail (info != NULL, FALSE); g_return_val_if_fail (info != NULL, FALSE);
buffer = meta->buffer; return meta->unmap (meta, plane, info);
g_return_val_if_fail (buffer != NULL, FALSE);
offset = meta->offset[plane];
/* move to the right offset inside the block */
info->data -= offset;
info->size += offset;
info->maxsize += offset;
gst_memory_unmap (info->memory, info);
gst_memory_unref (info->memory);
return TRUE;
} }
static void static void

View file

@ -44,8 +44,10 @@ typedef struct _GstVideoCropMeta GstVideoCropMeta;
* @width: the video width * @width: the video width
* @height: the video height * @height: the video height
* @n_planes: the number of planes in the image * @n_planes: the number of planes in the image
* @offset: array of offsets for the planes * @offset: array of offsets for the planes. This field might not always be
* @stride: array of strides for the planes * valid, it is used by the default implementation of @map.
* @stride: array of strides for the planes. This field might not always be
* valid, it is used by the default implementation of @map.
* @map: map the memory of a plane * @map: map the memory of a plane
* @unmap: unmap the memory of a plane * @unmap: unmap the memory of a plane
* *
@ -66,8 +68,8 @@ struct _GstVideoMeta {
gsize offset[GST_VIDEO_MAX_PLANES]; gsize offset[GST_VIDEO_MAX_PLANES];
gint stride[GST_VIDEO_MAX_PLANES]; gint stride[GST_VIDEO_MAX_PLANES];
gboolean (*map) (GstVideoMeta *meta, guint plane, GstMapInfo *info, gint *stride, gboolean (*map) (GstVideoMeta *meta, guint plane, GstMapInfo *info,
GstMapFlags flags); gpointer *data, gint * stride, GstMapFlags flags);
gboolean (*unmap) (GstVideoMeta *meta, guint plane, GstMapInfo *info); gboolean (*unmap) (GstVideoMeta *meta, guint plane, GstMapInfo *info);
}; };
@ -84,7 +86,7 @@ GstVideoMeta * gst_buffer_add_video_meta_full (GstBuffer *buffer, GstVideoFlags
gint stride[GST_VIDEO_MAX_PLANES]); gint stride[GST_VIDEO_MAX_PLANES]);
gboolean gst_video_meta_map (GstVideoMeta *meta, guint plane, GstMapInfo *info, gboolean gst_video_meta_map (GstVideoMeta *meta, guint plane, GstMapInfo *info,
gint *stride, GstMapFlags flags); gpointer *data, gint *stride, GstMapFlags flags);
gboolean gst_video_meta_unmap (GstVideoMeta *meta, guint plane, GstMapInfo *info); gboolean gst_video_meta_unmap (GstVideoMeta *meta, guint plane, GstMapInfo *info);
/** /**

View file

@ -1040,11 +1040,9 @@ gst_video_frame_map_id (GstVideoFrame * frame, GstVideoInfo * info,
frame->info.height = meta->height; frame->info.height = meta->height;
frame->id = meta->id; frame->id = meta->id;
for (i = 0; i < info->finfo->n_planes; i++) { for (i = 0; i < info->finfo->n_planes; i++)
gst_video_meta_map (meta, i, &frame->map[i], &frame->info.stride[i], gst_video_meta_map (meta, i, &frame->map[i], &frame->data[i],
flags); &frame->info.stride[i], flags);
frame->data[i] = frame->map[i].data;
}
} else { } else {
/* no metadata, we really need to have the metadata when the id is /* no metadata, we really need to have the metadata when the id is
* specified. */ * specified. */