video-frame: fix copy of tiled formats

Add code to copy tiled planes.

https://bugzilla.gnome.org/show_bug.cgi?id=707361
This commit is contained in:
Wim Taymans 2013-12-25 14:23:04 +01:00 committed by Nicolas Dufresne
parent 3ceb7dfe22
commit 980811c120
2 changed files with 77 additions and 19 deletions

View file

@ -203,6 +203,9 @@ typedef enum
#define GST_VIDEO_COMP_INDEX 0
#define GST_VIDEO_COMP_PALETTE 1
/* tile info component, we don't support planar alpha and tiled */
#define GST_VIDEO_COMP_TILEINFO 3
#include <gst/video/video-chroma.h>
/**

View file

@ -28,6 +28,7 @@
#include <gst/video/video.h>
#include "video-frame.h"
#include "video-tile.h"
#include "gstvideometa.h"
GST_DEBUG_CATEGORY_EXTERN (GST_CAT_PERFORMANCE);
@ -217,9 +218,9 @@ gst_video_frame_copy_plane (GstVideoFrame * dest, const GstVideoFrame * src,
{
const GstVideoInfo *sinfo;
GstVideoInfo *dinfo;
guint w, h, j;
const GstVideoFormatInfo *finfo;
guint8 *sp, *dp;
gint ss, ds;
guint w, h;
g_return_val_if_fail (dest != NULL, FALSE);
g_return_val_if_fail (src != NULL, FALSE);
@ -228,35 +229,89 @@ gst_video_frame_copy_plane (GstVideoFrame * dest, const GstVideoFrame * src,
dinfo = &dest->info;
g_return_val_if_fail (dinfo->finfo->format == sinfo->finfo->format, FALSE);
finfo = dinfo->finfo;
g_return_val_if_fail (dinfo->width == sinfo->width
&& dinfo->height == sinfo->height, FALSE);
g_return_val_if_fail (dinfo->finfo->n_planes > plane, FALSE);
g_return_val_if_fail (finfo->n_planes > plane, FALSE);
sp = src->data[plane];
dp = dest->data[plane];
if (plane == 1 && GST_VIDEO_FORMAT_INFO_HAS_PALETTE (sinfo->finfo)) {
ss = ds = 0;
w = 256 * 4;
h = 1;
if (GST_VIDEO_FORMAT_INFO_HAS_PALETTE (finfo) && plane == 1) {
/* copy the palette and we're done */
memcpy (dp, sp, 256 * 4);
return TRUE;
}
/* FIXME. assumes subsampling of component N is the same as plane N, which is
* currently true for all formats we have but it might not be in the future. */
w = GST_VIDEO_FRAME_COMP_WIDTH (dest,
plane) * GST_VIDEO_FRAME_COMP_PSTRIDE (dest, plane);
h = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane);
if (GST_VIDEO_FORMAT_INFO_IS_TILED (finfo)) {
gint tile_size;
gint sx_tiles, sy_tiles, dx_tiles, dy_tiles;
guint i, j, ws, hs, ts;
GstVideoTileMode mode;
gint tidx;
/* plane index of tile info */
tidx = finfo->n_planes - 1;
/* ignore tile info plane */
if (plane == tidx)
return TRUE;
ws = finfo->w_sub[GST_VIDEO_COMP_TILEINFO];
hs = finfo->h_sub[GST_VIDEO_COMP_TILEINFO];
ts = ws + hs;
tile_size = 1 << ts;
mode = finfo->pixel_stride[tidx];
sx_tiles = sinfo->stride[plane] >> ws;
sy_tiles = sinfo->stride[tidx];
dx_tiles = dinfo->stride[plane] >> ws;
dy_tiles = dinfo->stride[tidx];
/* this is the amount of tiles to copy */
w = (w + (1 << ws) - 1) >> ws;
h = (h + (1 << hs) - 1) >> hs;
/* FIXME can possibly do better when no retiling is needed, it depends on
* the stride and the tile_size */
for (j = 0; j < h; j++) {
for (i = 0; i < w; i++) {
guint si, di;
si = gst_video_tile_get_index (mode, i, j, sx_tiles, sy_tiles);
di = gst_video_tile_get_index (mode, i, j, dx_tiles, dy_tiles);
memcpy (dp + (di << ts), sp + (si << ts), tile_size);
}
}
} else {
gint ss, ds;
guint j;
ss = sinfo->stride[plane];
ds = dinfo->stride[plane];
/* FIXME. assumes subsampling of component N is the same as plane N, which is
* currently true for all formats we have but it might not be in the future. */
w = GST_VIDEO_FRAME_COMP_WIDTH (dest,
plane) * GST_VIDEO_FRAME_COMP_PSTRIDE (dest, plane);
h = GST_VIDEO_FRAME_COMP_HEIGHT (dest, plane);
GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy plane %d, w:%d h:%d ", plane, w,
h);
for (j = 0; j < h; j++) {
memcpy (dp, sp, w);
dp += ds;
sp += ss;
}
}
GST_CAT_DEBUG (GST_CAT_PERFORMANCE, "copy plane %d, w:%d h:%d ", plane, w, h);
for (j = 0; j < h; j++) {
memcpy (dp, sp, w);
dp += ds;
sp += ss;
}
return TRUE;
}