void (*matrix) (GstVideoConverter * convert, gpointer pixels);
void (*dither16) (GstVideoConverter * convert, guint16 * pixels, int j);
+ gboolean identity_unpack;
+ GstLineCache *unpack_lines;
GstLineCache *upsample_lines;
GstLineCache *hscale_lines;
GstLineCache *vscale_lines;
GstLineCache *convert_lines;
GstLineCache *downsample_lines;
GstLineCache *pack_lines;
+ gboolean identity_pack;
GstVideoScaler *h_scaler;
gint h_scale_format;
GstVideoFrame *dest;
};
-typedef gboolean (*GstLineCacheNeedLineFunc) (GstLineCache * cache, gint idx,
+typedef gpointer (*GstLineCacheAllocLineFunc) (GstLineCache * cache, gint idx,
gpointer user_data);
-typedef void (*GstLineCacheFreeLineFunc) (GstLineCache * cache, gint idx,
- gpointer line, gpointer user_data);
+typedef gboolean (*GstLineCacheNeedLineFunc) (GstLineCache * cache,
+ gint out_line, gint in_line, gpointer user_data);
struct _GstLineCache
{
gint first;
GPtrArray *lines;
+ GstLineCache *prev;
+ gboolean write_input;
+ gboolean pass_alloc;
+ gboolean alloc_writable;
GstLineCacheNeedLineFunc need_line;
gpointer need_line_data;
GDestroyNotify need_line_notify;
- GstLineCacheFreeLineFunc free_line;
- gpointer free_line_data;
- GDestroyNotify free_line_notify;
+ GstLineCacheAllocLineFunc alloc_line;
+ gpointer alloc_line_data;
+ GDestroyNotify alloc_line_notify;
};
static GstLineCache *
-gst_line_cache_new ()
+gst_line_cache_new (GstLineCache * prev)
{
GstLineCache *result;
result = g_slice_new0 (GstLineCache);
result->lines = g_ptr_array_new ();
+ result->prev = prev;
return result;
}
{
g_return_if_fail (cache != NULL);
- if (cache->free_line) {
- gint i;
- for (i = 0; i < cache->lines->len; i++)
- cache->free_line (cache, cache->first + i,
- *(cache->lines->pdata + i), cache->free_line_data);
- }
g_ptr_array_set_size (cache->lines, 0);
cache->first = 0;
}
}
static void
-gst_line_cache_set_free_line_func (GstLineCache * cache,
- GstLineCacheFreeLineFunc free_line, gpointer user_data,
+gst_line_cache_set_alloc_line_func (GstLineCache * cache,
+ GstLineCacheAllocLineFunc alloc_line, gpointer user_data,
GDestroyNotify notify)
{
- cache->free_line = free_line;
- cache->free_line_data = user_data;
- cache->free_line_notify = notify;
+ cache->alloc_line = alloc_line;
+ cache->alloc_line_data = user_data;
+ cache->alloc_line_notify = notify;
}
static gpointer *
-gst_line_cache_get_lines (GstLineCache * cache, gint idx, gint n_lines)
-{
- if (cache->first < idx) {
- gint i, to_remove = MIN (idx - cache->first, cache->lines->len);
- if (cache->free_line) {
- for (i = 0; i < to_remove; i++)
- cache->free_line (cache, cache->first + i,
- *(cache->lines->pdata + i), cache->free_line_data);
- }
+gst_line_cache_get_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gint n_lines)
+{
+ if (cache->first < in_line) {
+ gint to_remove = MIN (in_line - cache->first, cache->lines->len);
if (to_remove > 0)
g_ptr_array_remove_range (cache->lines, 0, to_remove);
- cache->first = idx;
- } else if (idx < cache->first) {
+ cache->first = in_line;
+ } else if (in_line < cache->first) {
gst_line_cache_clear (cache);
- cache->first = idx;
+ cache->first = in_line;
}
while (TRUE) {
- if (cache->first <= idx
- && idx + n_lines <= cache->first + (gint) cache->lines->len) {
- return cache->lines->pdata + (idx - cache->first);
+ if (cache->first <= in_line
+ && in_line + n_lines <= cache->first + (gint) cache->lines->len) {
+ return cache->lines->pdata + (in_line - cache->first);
}
if (cache->need_line == NULL)
break;
- if (!cache->need_line (cache, cache->first + cache->lines->len,
+ if (!cache->need_line (cache, out_line, cache->first + cache->lines->len,
cache->need_line_data))
break;
}
g_ptr_array_add (cache->lines, line);
}
+static gpointer
+gst_line_cache_alloc_line (GstLineCache * cache, gint idx)
+{
+ gpointer res;
+
+ if (cache->alloc_line)
+ res = cache->alloc_line (cache, idx, cache->alloc_line_data);
+ else
+ res = NULL;
+
+ return res;
+}
+
static void video_converter_generic (GstVideoConverter * convert,
const GstVideoFrame * src, GstVideoFrame * dest);
static void video_converter_matrix8 (GstVideoConverter * convert,
static void video_converter_compute_matrix (GstVideoConverter * convert);
static void video_converter_compute_resample (GstVideoConverter * convert);
-static gboolean do_unpack_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
-static gboolean do_downsample_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
-static gboolean do_convert_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
-static gboolean do_upsample_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
-static gboolean do_vscale_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
-static gboolean do_hscale_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert);
+static gpointer get_dest_line (GstLineCache * cache, gint idx,
+ gpointer user_data);
-static void
-free_pack_line (GstLineCache * cache, gint idx,
- gpointer line, gpointer user_data)
-{
- GST_DEBUG ("line %d %p", idx, line);
-}
+static gboolean do_unpack_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
+static gboolean do_downsample_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
+static gboolean do_convert_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
+static gboolean do_upsample_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
+static gboolean do_vscale_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
+static gboolean do_hscale_lines (GstLineCache * cache, gint out_line,
+ gint in_line, gpointer user_data);
static void
alloc_tmplines (GstVideoConverter * convert, guint lines, gint width)
}
static gpointer
-get_temp_line (GstVideoConverter * convert, gint offset)
+get_temp_line (GstLineCache * cache, gint idx, gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer tmpline;
+ GST_DEBUG ("get temp line %d", idx);
tmpline = (guint8 *) convert->tmplines[convert->tmplines_idx] +
- (offset * convert->pack_pstride);
+ (convert->out_x * convert->pack_pstride);
convert->tmplines_idx = (convert->tmplines_idx + 1) % convert->n_tmplines;
return tmpline;
}
-static GstLineCacheNeedLineFunc
+static GstLineCache *
chain_unpack_line (GstVideoConverter * convert)
{
- convert->current_format = convert->in_info.finfo->format;
+ GstLineCache *prev;
+
+ convert->current_format = convert->in_info.finfo->unpack_format;
convert->current_pstride = convert->in_bits >> 1;
- return (GstLineCacheNeedLineFunc) do_unpack_lines;
+
+ convert->identity_unpack =
+ (convert->current_format == convert->in_info.finfo->format);
+
+ prev = convert->unpack_lines = gst_line_cache_new (NULL);
+ prev->write_input = FALSE;
+ prev->pass_alloc = FALSE;
+ gst_line_cache_set_need_line_func (convert->unpack_lines,
+ do_unpack_lines, convert, NULL);
+
+ return convert->unpack_lines;
}
-static GstLineCacheNeedLineFunc
-chain_upsample (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
+static GstLineCache *
+chain_upsample (GstVideoConverter * convert, GstLineCache * prev)
{
video_converter_compute_resample (convert);
if (convert->upsample) {
- convert->upsample_lines = gst_line_cache_new ();
+ prev = convert->upsample_lines = gst_line_cache_new (prev);
+ prev->write_input = TRUE;
+ prev->pass_alloc = TRUE;
gst_line_cache_set_need_line_func (convert->upsample_lines,
- need_line, convert, NULL);
- need_line = (GstLineCacheNeedLineFunc) do_upsample_lines;
+ do_upsample_lines, convert, NULL);
}
- return need_line;
+ return prev;
}
-static GstLineCacheNeedLineFunc
-chain_convert (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
-{
- convert->convert_lines = gst_line_cache_new ();
- gst_line_cache_set_need_line_func (convert->convert_lines,
- need_line, convert, NULL);
- convert->current_format = convert->out_info.finfo->format;
+static GstLineCache *
+chain_convert (GstVideoConverter * convert, GstLineCache * prev)
+{
+ if (convert->in_bits != convert->out_bits || convert->matrix) {
+ prev = convert->convert_lines = gst_line_cache_new (prev);
+ prev->write_input = TRUE;
+ prev->pass_alloc = TRUE;
+ gst_line_cache_set_need_line_func (convert->convert_lines,
+ do_convert_lines, convert, NULL);
+ }
+ convert->current_format = convert->out_info.finfo->unpack_format;
convert->current_pstride = convert->out_bits >> 1;
- return (GstLineCacheNeedLineFunc) do_convert_lines;
+
+ return prev;
}
-static GstLineCacheNeedLineFunc
-chain_hscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
+static GstLineCache *
+chain_hscale (GstVideoConverter * convert, GstLineCache * prev)
{
gint method;
guint taps;
- convert->hscale_lines = gst_line_cache_new ();
+ prev = convert->hscale_lines = gst_line_cache_new (prev);
+ prev->write_input = FALSE;
+ prev->pass_alloc = FALSE;
gst_line_cache_set_need_line_func (convert->hscale_lines,
- need_line, convert, NULL);
+ do_hscale_lines, convert, NULL);
if (!gst_structure_get_enum (convert->config,
GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
convert->current_width = convert->out_width;
convert->h_scale_format = convert->current_format;
- return (GstLineCacheNeedLineFunc) do_hscale_lines;
+ return prev;
}
-static GstLineCacheNeedLineFunc
-chain_vscale (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
+static GstLineCache *
+chain_vscale (GstVideoConverter * convert, GstLineCache * prev)
{
GstVideoScalerFlags flags;
gint method;
flags = GST_VIDEO_INFO_IS_INTERLACED (&convert->in_info) ?
GST_VIDEO_SCALER_FLAG_INTERLACED : 0;
- convert->vscale_lines = gst_line_cache_new ();
- gst_line_cache_set_need_line_func (convert->vscale_lines,
- need_line, convert, NULL);
-
if (!gst_structure_get_enum (convert->config,
GST_VIDEO_CONVERTER_OPT_RESAMPLER_METHOD,
GST_TYPE_VIDEO_RESAMPLER_METHOD, &method))
convert->v_scale_width = convert->current_width;
convert->v_scale_format = convert->current_format;
- return (GstLineCacheNeedLineFunc) do_vscale_lines;
+ gst_video_scaler_get_coeff (convert->v_scaler, 0, NULL, &taps);
+
+ prev = convert->vscale_lines = gst_line_cache_new (prev);
+ prev->pass_alloc = (taps == 1);
+ prev->write_input = FALSE;
+ gst_line_cache_set_need_line_func (convert->vscale_lines,
+ do_vscale_lines, convert, NULL);
+
+ return prev;
}
-static GstLineCacheNeedLineFunc
-chain_downsample (GstVideoConverter * convert,
- GstLineCacheNeedLineFunc need_line)
+static GstLineCache *
+chain_downsample (GstVideoConverter * convert, GstLineCache * prev)
{
if (convert->downsample) {
- convert->downsample_lines = gst_line_cache_new ();
+ prev = convert->downsample_lines = gst_line_cache_new (prev);
+ prev->write_input = TRUE;
+ prev->pass_alloc = TRUE;
gst_line_cache_set_need_line_func (convert->downsample_lines,
- need_line, convert, NULL);
- need_line = (GstLineCacheNeedLineFunc) do_downsample_lines;
+ do_downsample_lines, convert, NULL);
}
- return need_line;
+ return prev;
}
-static GstLineCacheNeedLineFunc
-chain_pack (GstVideoConverter * convert, GstLineCacheNeedLineFunc need_line)
+static GstLineCache *
+chain_pack (GstVideoConverter * convert, GstLineCache * prev)
{
- convert->pack_lines = gst_line_cache_new ();
- gst_line_cache_set_need_line_func (convert->pack_lines,
- need_line, convert, NULL);
- gst_line_cache_set_free_line_func (convert->pack_lines,
- (GstLineCacheFreeLineFunc) free_pack_line, convert, NULL);
convert->pack_pstride = convert->current_pstride;
- return NULL;
+ convert->identity_pack =
+ (convert->out_info.finfo->format ==
+ convert->out_info.finfo->unpack_format);
+
+ return prev;
}
static gint
return res;
}
+static void
+setup_allocators (GstVideoConverter * convert)
+{
+ GstLineCache *cache;
+ GstLineCacheAllocLineFunc alloc_line;
+ gboolean alloc_writable = FALSE;
+
+ /* start with using dest lines if we can directly write into it */
+ if (convert->identity_pack)
+ alloc_line = get_dest_line;
+ else
+ alloc_line = get_temp_line;
+
+ /* now walk backwards, we try to write into the dest lines directly
+ * and keep track if the source needs to be writable */
+ for (cache = convert->pack_lines; cache; cache = cache->prev) {
+ gst_line_cache_set_alloc_line_func (cache, alloc_line, convert, NULL);
+ cache->alloc_writable = alloc_writable;
+
+ if (cache->pass_alloc == FALSE) {
+ /* can't pass allocator, use temp lines */
+ alloc_line = get_temp_line;
+ alloc_writable = FALSE;
+ }
+ /* if someone writes to the input, we need a writable line from the
+ * previous cache */
+ if (cache->write_input)
+ alloc_writable = TRUE;
+ }
+}
+
/**
* gst_video_converter_new:
* @in_info: a #GstVideoInfo
{
GstVideoConverter *convert;
gint width;
- GstLineCacheNeedLineFunc need_line;
+ GstLineCache *prev;
gint s2, s3;
const GstVideoFormatInfo *fin, *fout;
convert->current_width = convert->in_width;
/* unpack */
- need_line = chain_unpack_line (convert);
+ prev = chain_unpack_line (convert);
/* upsample chroma */
- need_line = chain_upsample (convert, need_line);
+ prev = chain_upsample (convert, prev);
if (s3 <= s2) {
/* horizontal scaling first produces less pixels */
if (convert->in_width <= convert->out_width) {
/* upscaling, first convert then */
- need_line = chain_convert (convert, need_line);
+ prev = chain_convert (convert, prev);
}
if (convert->in_width != convert->out_width) {
- need_line = chain_hscale (convert, need_line);
+ prev = chain_hscale (convert, prev);
}
if (convert->in_width > convert->out_width) {
/* downscaling, convert after scaling then */
- need_line = chain_convert (convert, need_line);
+ prev = chain_convert (convert, prev);
}
}
/* v-scale */
if (convert->in_height != convert->out_height) {
- need_line = chain_vscale (convert, need_line);
+ prev = chain_vscale (convert, prev);
}
if (s3 > s2) {
/* vertical scaling first produced less pixels */
if (convert->in_width <= convert->out_width) {
/* upscaling, first convert then */
- need_line = chain_convert (convert, need_line);
+ prev = chain_convert (convert, prev);
}
if (convert->in_width != convert->out_width) {
- need_line = chain_hscale (convert, need_line);
+ prev = chain_hscale (convert, prev);
}
if (convert->in_width > convert->out_width) {
/* downscaling, convert after scaling then */
- need_line = chain_convert (convert, need_line);
+ prev = chain_convert (convert, prev);
}
}
/* downsample chroma */
- need_line = chain_downsample (convert, need_line);
+ prev = chain_downsample (convert, prev);
/* pack into final format */
- need_line = chain_pack (convert, need_line);
+ convert->pack_lines = chain_pack (convert, prev);
+
+ /* now figure out allocators */
+ setup_allocators (convert);
convert->lines = out_info->finfo->pack_lines;
width = MAX (convert->in_maxwidth, convert->out_maxwidth);
if (convert->h_scaler)
gst_video_scaler_free (convert->h_scaler);
+ if (convert->unpack_lines)
+ gst_line_cache_free (convert->unpack_lines);
if (convert->upsample_lines)
gst_line_cache_free (convert->upsample_lines);
if (convert->hscale_lines)
gst_line_cache_free (convert->convert_lines);
if (convert->downsample_lines)
gst_line_cache_free (convert->downsample_lines);
- if (convert->pack_lines)
- gst_line_cache_free (convert->pack_lines);
for (i = 0; i < convert->n_tmplines; i++)
g_free (convert->tmplines[i]);
line8[i] = line16[i] >> 8;
}
+#define FRAME_GET_PLANE_STRIDE(frame, plane) \
+ GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
+#define FRAME_GET_PLANE_LINE(frame, plane, line) \
+ (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
+ FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
+
+#define FRAME_GET_COMP_STRIDE(frame, comp) \
+ GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
+#define FRAME_GET_COMP_LINE(frame, comp, line) \
+ (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
+ FRAME_GET_COMP_STRIDE (frame, comp) * (line))
+
+#define FRAME_GET_STRIDE(frame) FRAME_GET_PLANE_STRIDE (frame, 0)
+#define FRAME_GET_LINE(frame,line) FRAME_GET_PLANE_LINE (frame, 0, line)
+
+#define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
+#define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
+#define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
+#define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
+
+#define FRAME_GET_Y_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
+#define FRAME_GET_U_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
+#define FRAME_GET_V_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
+#define FRAME_GET_A_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
+
+
#define UNPACK_FRAME(frame,dest,line,x,width) \
frame->info.finfo->unpack_func (frame->info.finfo, \
(GST_VIDEO_FRAME_IS_INTERLACED (frame) ? \
src, 0, frame->data, frame->info.stride, \
frame->info.chroma_site, line, width);
+
+static gpointer
+get_dest_line (GstLineCache * cache, gint idx, gpointer user_data)
+{
+ GstVideoConverter *convert = user_data;
+ guint8 *line;
+
+ GST_DEBUG ("get dest line %d", idx);
+ line = FRAME_GET_LINE (convert->dest, idx);
+ line += convert->out_x * convert->pack_pstride;
+ return line;
+}
+
static gboolean
-do_unpack_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
+do_unpack_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer tmpline;
guint cline;
- cline = CLAMP (line + convert->in_y, 0, convert->in_maxheight - 1);
+ cline = CLAMP (in_line + convert->in_y, 0, convert->in_maxheight - 1);
- /* FIXME we should be able to use the input line without unpack if the
- * format is already suitable. When we do this, we should be careful not to
- * do in-place modifications. */
- GST_DEBUG ("unpack line %d (%u)", line, cline);
- tmpline = get_temp_line (convert, convert->out_x);
-
- UNPACK_FRAME (convert->src, tmpline, cline, convert->in_x, convert->in_width);
-
- gst_line_cache_add_line (cache, line, tmpline);
+ if (cache->alloc_writable || !convert->identity_unpack) {
+ tmpline = gst_line_cache_alloc_line (cache, out_line);
+ GST_DEBUG ("unpack line %d (%u) %p", in_line, cline, tmpline);
+ UNPACK_FRAME (convert->src, tmpline, cline, convert->in_x,
+ convert->in_width);
+ } else {
+ GST_DEBUG ("get src line %d (%u)", in_line, cline);
+ tmpline = FRAME_GET_LINE (convert->src, cline);
+ }
+ gst_line_cache_add_line (cache, in_line, tmpline);
return TRUE;
}
static gboolean
-do_upsample_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
+do_upsample_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer *lines;
gint i, start_line, n_lines;
n_lines = convert->up_n_lines;
- start_line = line;
+ start_line = in_line;
if (start_line < n_lines + convert->up_offset)
start_line += convert->up_offset;
/* get the lines needed for chroma upsample */
- lines =
- gst_line_cache_get_lines (convert->upsample_lines, start_line, n_lines);
+ lines = gst_line_cache_get_lines (cache->prev, out_line, start_line, n_lines);
GST_DEBUG ("doing upsample %d-%d", start_line, start_line + n_lines - 1);
gst_video_chroma_resample (convert->upsample, lines, convert->in_width);
}
static gboolean
-do_hscale_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
+do_hscale_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer *lines, destline;
- lines = gst_line_cache_get_lines (convert->hscale_lines, line, 1);
+ lines = gst_line_cache_get_lines (cache->prev, out_line, in_line, 1);
- destline = get_temp_line (convert, convert->out_x);
+ destline = gst_line_cache_alloc_line (cache, out_line);
- GST_DEBUG ("hresample line %d", line);
+ GST_DEBUG ("hresample line %d", in_line);
gst_video_scaler_horizontal (convert->h_scaler, convert->h_scale_format,
lines[0], destline, 0, convert->out_width);
- gst_line_cache_add_line (cache, line, destline);
+ gst_line_cache_add_line (cache, in_line, destline);
return TRUE;
}
static gboolean
-do_vscale_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
+do_vscale_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer *lines, destline;
guint sline, n_lines;
guint cline;
- cline = CLAMP (line, 0, convert->out_height - 1);
+ cline = CLAMP (in_line, 0, convert->out_height - 1);
gst_video_scaler_get_coeff (convert->v_scaler, cline, &sline, &n_lines);
- lines = gst_line_cache_get_lines (convert->vscale_lines, sline, n_lines);
+ lines = gst_line_cache_get_lines (cache->prev, out_line, sline, n_lines);
- destline = get_temp_line (convert, convert->out_x);
+ destline = gst_line_cache_alloc_line (cache, out_line);
- /* FIXME with 1-tap (nearest), we can simply copy the input line. We need
- * to be careful to not do in-place modifications later */
- GST_DEBUG ("vresample line %d %d-%d", line, sline, sline + n_lines - 1);
+ GST_DEBUG ("vresample line %d %d-%d", in_line, sline, sline + n_lines - 1);
gst_video_scaler_vertical (convert->v_scaler, convert->v_scale_format,
lines, destline, cline, convert->v_scale_width);
- gst_line_cache_add_line (cache, line, destline);
+ gst_line_cache_add_line (cache, in_line, destline);
return TRUE;
}
static gboolean
-do_convert_lines (GstLineCache * cache, gint line, GstVideoConverter * convert)
+do_convert_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer *lines;
guint in_bits, out_bits;
gint width;
- lines = gst_line_cache_get_lines (convert->convert_lines, line, 1);
+ lines = gst_line_cache_get_lines (cache->prev, out_line, in_line, 1);
in_bits = convert->in_bits;
out_bits = convert->out_bits;
width = MIN (convert->in_width, convert->out_width);
- GST_DEBUG ("convert line %d", line);
+ GST_DEBUG ("convert line %d", in_line);
if (out_bits == 16 || in_bits == 16) {
/* FIXME, we can scale in the conversion matrix */
if (in_bits == 8)
if (convert->matrix)
convert->matrix (convert, lines[0]);
if (convert->dither16)
- convert->dither16 (convert, lines[0], line);
+ convert->dither16 (convert, lines[0], in_line);
if (out_bits == 8)
convert_to8 (lines[0], width);
if (convert->matrix)
convert->matrix (convert, lines[0]);
}
- gst_line_cache_add_line (cache, line, lines[0]);
+ gst_line_cache_add_line (cache, in_line, lines[0]);
return TRUE;
}
static gboolean
-do_downsample_lines (GstLineCache * cache, gint line,
- GstVideoConverter * convert)
+do_downsample_lines (GstLineCache * cache, gint out_line, gint in_line,
+ gpointer user_data)
{
+ GstVideoConverter *convert = user_data;
gpointer *lines;
gint i, start_line, n_lines;
n_lines = convert->down_n_lines;
- start_line = line;
+ start_line = in_line;
if (start_line < n_lines + convert->down_offset)
start_line += convert->down_offset;
/* get the lines needed for chroma downsample */
- lines =
- gst_line_cache_get_lines (convert->downsample_lines, start_line, n_lines);
+ lines = gst_line_cache_get_lines (cache->prev, out_line, start_line, n_lines);
- GST_DEBUG ("downsample line %d %d-%d", line, start_line,
+ GST_DEBUG ("downsample line %d %d-%d", in_line, start_line,
start_line + n_lines - 1);
gst_video_chroma_resample (convert->downsample, lines, convert->out_width);
guint8 *l;
/* load the lines needed to pack */
- lines = gst_line_cache_get_lines (convert->pack_lines, i, pack_lines);
+ lines =
+ gst_line_cache_get_lines (convert->pack_lines, i + out_y, i,
+ pack_lines);
/* take away the border */
l = ((guint8 *) lines[0]) - lb_width;
memcpy (l, convert->borderline, lb_width);
memcpy (l + r_border, convert->borderline, rb_width);
}
- /* and pack into destination */
- /* FIXME, we should be able to convert directly into the destination line
- * when the output format is in the right format */
- GST_DEBUG ("pack line %d", i + out_y);
- PACK_FRAME (dest, l, i + out_y, out_maxwidth);
+ if (!convert->identity_pack) {
+ /* and pack into destination */
+ GST_DEBUG ("pack line %d", i + out_y);
+ PACK_FRAME (dest, l, i + out_y, out_maxwidth);
+ }
}
if (convert->borderline) {
}
}
-#define FRAME_GET_PLANE_STRIDE(frame, plane) \
- GST_VIDEO_FRAME_PLANE_STRIDE (frame, plane)
-#define FRAME_GET_PLANE_LINE(frame, plane, line) \
- (gpointer)(((guint8*)(GST_VIDEO_FRAME_PLANE_DATA (frame, plane))) + \
- FRAME_GET_PLANE_STRIDE (frame, plane) * (line))
-
-#define FRAME_GET_COMP_STRIDE(frame, comp) \
- GST_VIDEO_FRAME_COMP_STRIDE (frame, comp)
-#define FRAME_GET_COMP_LINE(frame, comp, line) \
- (gpointer)(((guint8*)(GST_VIDEO_FRAME_COMP_DATA (frame, comp))) + \
- FRAME_GET_COMP_STRIDE (frame, comp) * (line))
-
-#define FRAME_GET_STRIDE(frame) FRAME_GET_PLANE_STRIDE (frame, 0)
-#define FRAME_GET_LINE(frame,line) FRAME_GET_PLANE_LINE (frame, 0, line)
-
-#define FRAME_GET_Y_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_Y, line)
-#define FRAME_GET_U_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_U, line)
-#define FRAME_GET_V_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_V, line)
-#define FRAME_GET_A_LINE(frame,line) FRAME_GET_COMP_LINE(frame, GST_VIDEO_COMP_A, line)
-
-#define FRAME_GET_Y_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_Y)
-#define FRAME_GET_U_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_U)
-#define FRAME_GET_V_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_V)
-#define FRAME_GET_A_STRIDE(frame) FRAME_GET_COMP_STRIDE(frame, GST_VIDEO_COMP_A)
-
/* Fast paths */
#define GET_LINE_OFFSETS(interlaced,line,l1,l2) \