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;
}
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:
* @buffer: a #GstBuffer
@ -161,59 +226,18 @@ gst_buffer_add_video_meta_full (GstBuffer * buffer, GstVideoFlags flags,
meta->offset[i] = offset[i];
meta->stride[i] = stride[i];
}
meta->map = default_map;
meta->unmap = default_unmap;
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:
* @meta: a #GstVideoMeta
* @plane: a plane
* @info: a #GstMapInfo
* @stride: result stride
* @offset: the offset of where the plane starts in @info
* @flags: @GstMapFlags
*
* Map the video plane with index @plane in @meta and return a pointer to the
@ -223,36 +247,19 @@ cannot_map:
*/
gboolean
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->map != NULL, FALSE);
g_return_val_if_fail (plane < meta->n_planes, 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 (meta->buffer != NULL, FALSE);
g_return_val_if_fail (!(flags & GST_MAP_WRITE)
|| gst_buffer_is_writable (meta->buffer), FALSE);
buffer = meta->buffer;
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;
return meta->map (meta, plane, info, data, stride, flags);
}
/**
@ -268,27 +275,12 @@ gst_video_meta_map (GstVideoMeta * meta, guint plane, GstMapInfo * info,
gboolean
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->unmap != NULL, FALSE);
g_return_val_if_fail (plane < meta->n_planes, FALSE);
g_return_val_if_fail (info != NULL, FALSE);
buffer = meta->buffer;
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;
return meta->unmap (meta, plane, info);
}
static void

View file

@ -44,8 +44,10 @@ typedef struct _GstVideoCropMeta GstVideoCropMeta;
* @width: the video width
* @height: the video height
* @n_planes: the number of planes in the image
* @offset: array of offsets for the planes
* @stride: array of strides for the planes
* @offset: array of offsets for the planes. This field might not always be
* 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
* @unmap: unmap the memory of a plane
*
@ -66,8 +68,8 @@ struct _GstVideoMeta {
gsize offset[GST_VIDEO_MAX_PLANES];
gint stride[GST_VIDEO_MAX_PLANES];
gboolean (*map) (GstVideoMeta *meta, guint plane, GstMapInfo *info, gint *stride,
GstMapFlags flags);
gboolean (*map) (GstVideoMeta *meta, guint plane, GstMapInfo *info,
gpointer *data, gint * stride, GstMapFlags flags);
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]);
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);
/**

View file

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