summaryrefslogtreecommitdiff
path: root/gst/videoscale
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2009-07-28 13:55:30 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2009-08-06 06:43:31 +0200
commit33c490f4b9b5642a601515eae245a4812887d755 (patch)
tree5df0fe1ae9949a08276a236519b1d674c21cad07 /gst/videoscale
parent0a8bb8cb53fc09fe4d0a00db8e40bdc7f8efa712 (diff)
videoscale: Add support for interlaced content
videoscale is not mixing content of two seperate fields anymore and does scaling on every field separately. Fixes bug #588761.
Diffstat (limited to 'gst/videoscale')
-rw-r--r--gst/videoscale/gstvideoscale.c379
-rw-r--r--gst/videoscale/gstvideoscale.h1
2 files changed, 211 insertions, 169 deletions
diff --git a/gst/videoscale/gstvideoscale.c b/gst/videoscale/gstvideoscale.c
index 252d8ae1d..10136a737 100644
--- a/gst/videoscale/gstvideoscale.c
+++ b/gst/videoscale/gstvideoscale.c
@@ -494,7 +494,8 @@ unknown_format:
}
static gboolean
-parse_caps (GstCaps * caps, gint * format, gint * width, gint * height)
+parse_caps (GstCaps * caps, gint * format, gint * width, gint * height,
+ gboolean * interlaced)
{
gboolean ret;
GstStructure *structure;
@@ -506,6 +507,11 @@ parse_caps (GstCaps * caps, gint * format, gint * width, gint * height)
if (format)
*format = gst_video_scale_get_format (caps);
+ if (interlaced) {
+ *interlaced = FALSE;
+ gst_structure_get_boolean (structure, "interlaced", interlaced);
+ }
+
return ret;
}
@@ -518,8 +524,10 @@ gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out)
videoscale = GST_VIDEO_SCALE (trans);
ret = parse_caps (in, &videoscale->format, &videoscale->from_width,
- &videoscale->from_height);
- ret &= parse_caps (out, NULL, &videoscale->to_width, &videoscale->to_height);
+ &videoscale->from_height, &videoscale->interlaced);
+ ret &=
+ parse_caps (out, NULL, &videoscale->to_width, &videoscale->to_height,
+ NULL);
if (!ret)
goto done;
@@ -561,7 +569,7 @@ gst_video_scale_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
videoscale = GST_VIDEO_SCALE (trans);
- if (!parse_caps (caps, &format, &width, &height))
+ if (!parse_caps (caps, &format, &width, &height, NULL))
return FALSE;
if (!gst_video_scale_prepare_size (videoscale, format, &img, width, height,
@@ -696,7 +704,8 @@ gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction,
static gboolean
gst_video_scale_prepare_image (gint format, GstBuffer * buf,
- VSImage * img, VSImage * img_u, VSImage * img_v)
+ VSImage * img, VSImage * img_u, VSImage * img_v, gint step,
+ gboolean interlaced)
{
gboolean res = TRUE;
@@ -707,10 +716,19 @@ gst_video_scale_prepare_image (gint format, GstBuffer * buf,
case GST_VIDEO_SCALE_YV12:
img_u->pixels = img->pixels + GST_ROUND_UP_2 (img->height) * img->stride;
img_u->height = GST_ROUND_UP_2 (img->height) / 2;
+ if (interlaced) {
+ img_u->height = (img_u->height / 2) + ((step == 0
+ && img_u->height % 2 == 1) ? 1 : 0);
+ img_u->stride *= 2;
+ }
img_u->width = GST_ROUND_UP_2 (img->width) / 2;
img_u->stride = GST_ROUND_UP_4 (img_u->width);
memcpy (img_v, img_u, sizeof (*img_v));
img_v->pixels = img_u->pixels + img_u->height * img_u->stride;
+ if (interlaced && step == 1) {
+ img_v->pixels += (img_v->stride / 2);
+ img_u->pixels += (img_u->stride / 2);
+ }
break;
default:
break;
@@ -722,182 +740,205 @@ static GstFlowReturn
gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in,
GstBuffer * out)
{
- GstVideoScale *videoscale;
+ GstVideoScale *videoscale = GST_VIDEO_SCALE (trans);
GstFlowReturn ret = GST_FLOW_OK;
- VSImage *dest;
- VSImage *src;
- VSImage dest_u;
- VSImage dest_v;
- VSImage src_u;
- VSImage src_v;
+ VSImage dest = videoscale->dest;
+ VSImage src = videoscale->src;
+ VSImage dest_u = { NULL, };
+ VSImage dest_v = { NULL, };
+ VSImage src_u = { NULL, };
+ VSImage src_v = { NULL, };
gint method;
-
- videoscale = GST_VIDEO_SCALE (trans);
+ gint step;
+ gboolean interlaced = videoscale->interlaced;
GST_OBJECT_LOCK (videoscale);
method = videoscale->method;
GST_OBJECT_UNLOCK (videoscale);
- src = &videoscale->src;
- dest = &videoscale->dest;
+ if (src.height < 4 && method == GST_VIDEO_SCALE_4TAP)
+ method = GST_VIDEO_SCALE_BILINEAR;
- gst_video_scale_prepare_image (videoscale->format, in, src, &src_u, &src_v);
- gst_video_scale_prepare_image (videoscale->format, out, dest, &dest_u,
- &dest_v);
+ /* For interlaced content we have to run two times with half height
+ * and doubled stride */
+ if (videoscale->interlaced) {
+ dest.height /= 2;
+ src.height /= 2;
+ dest.stride *= 2;
+ src.stride *= 2;
+ }
- if (src->height < 4 && method == GST_VIDEO_SCALE_4TAP)
- method = GST_VIDEO_SCALE_BILINEAR;
+ for (step = 0; step < (interlaced ? 2 : 1); step++) {
+ gst_video_scale_prepare_image (videoscale->format, in, &src, &src_u, &src_v,
+ step, interlaced);
+ gst_video_scale_prepare_image (videoscale->format, out, &dest, &dest_u,
+ &dest_v, step, interlaced);
- switch (method) {
- case GST_VIDEO_SCALE_NEAREST:
- GST_LOG_OBJECT (videoscale, "doing nearest scaling");
- switch (videoscale->format) {
- case GST_VIDEO_SCALE_RGBx:
- case GST_VIDEO_SCALE_xRGB:
- case GST_VIDEO_SCALE_BGRx:
- case GST_VIDEO_SCALE_xBGR:
- case GST_VIDEO_SCALE_RGBA:
- case GST_VIDEO_SCALE_ARGB:
- case GST_VIDEO_SCALE_BGRA:
- case GST_VIDEO_SCALE_ABGR:
- case GST_VIDEO_SCALE_AYUV:
- vs_image_scale_nearest_RGBA (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB:
- case GST_VIDEO_SCALE_BGR:
- case GST_VIDEO_SCALE_v308:
- vs_image_scale_nearest_RGB (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_YUY2:
- case GST_VIDEO_SCALE_YVYU:
- vs_image_scale_nearest_YUYV (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_UYVY:
- vs_image_scale_nearest_UYVY (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_Y:
- case GST_VIDEO_SCALE_GRAY8:
- vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_GRAY16:
- vs_image_scale_nearest_Y16 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_I420:
- case GST_VIDEO_SCALE_YV12:
- vs_image_scale_nearest_Y (dest, src, videoscale->tmp_buf);
- vs_image_scale_nearest_Y (&dest_u, &src_u, videoscale->tmp_buf);
- vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB565:
- vs_image_scale_nearest_RGB565 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB555:
- vs_image_scale_nearest_RGB555 (dest, src, videoscale->tmp_buf);
- break;
- default:
- goto unsupported;
+ if (step == 0 && interlaced) {
+ if (videoscale->from_height % 2 == 1) {
+ src.height += 1;
}
- break;
- case GST_VIDEO_SCALE_BILINEAR:
- GST_LOG_OBJECT (videoscale, "doing bilinear scaling");
- switch (videoscale->format) {
- case GST_VIDEO_SCALE_RGBx:
- case GST_VIDEO_SCALE_xRGB:
- case GST_VIDEO_SCALE_BGRx:
- case GST_VIDEO_SCALE_xBGR:
- case GST_VIDEO_SCALE_RGBA:
- case GST_VIDEO_SCALE_ARGB:
- case GST_VIDEO_SCALE_BGRA:
- case GST_VIDEO_SCALE_ABGR:
- case GST_VIDEO_SCALE_AYUV:
- vs_image_scale_linear_RGBA (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB:
- case GST_VIDEO_SCALE_BGR:
- case GST_VIDEO_SCALE_v308:
- vs_image_scale_linear_RGB (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_YUY2:
- case GST_VIDEO_SCALE_YVYU:
- vs_image_scale_linear_YUYV (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_UYVY:
- vs_image_scale_linear_UYVY (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_Y:
- case GST_VIDEO_SCALE_GRAY8:
- vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_GRAY16:
- vs_image_scale_linear_Y16 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_I420:
- case GST_VIDEO_SCALE_YV12:
- vs_image_scale_linear_Y (dest, src, videoscale->tmp_buf);
- vs_image_scale_linear_Y (&dest_u, &src_u, videoscale->tmp_buf);
- vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB565:
- vs_image_scale_linear_RGB565 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB555:
- vs_image_scale_linear_RGB555 (dest, src, videoscale->tmp_buf);
- break;
- default:
- goto unsupported;
- }
- break;
- case GST_VIDEO_SCALE_4TAP:
- GST_LOG_OBJECT (videoscale, "doing 4tap scaling");
- switch (videoscale->format) {
- case GST_VIDEO_SCALE_RGBx:
- case GST_VIDEO_SCALE_xRGB:
- case GST_VIDEO_SCALE_BGRx:
- case GST_VIDEO_SCALE_xBGR:
- case GST_VIDEO_SCALE_RGBA:
- case GST_VIDEO_SCALE_ARGB:
- case GST_VIDEO_SCALE_BGRA:
- case GST_VIDEO_SCALE_ABGR:
- case GST_VIDEO_SCALE_AYUV:
- vs_image_scale_4tap_RGBA (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB:
- case GST_VIDEO_SCALE_BGR:
- case GST_VIDEO_SCALE_v308:
- vs_image_scale_4tap_RGB (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_YUY2:
- case GST_VIDEO_SCALE_YVYU:
- vs_image_scale_4tap_YUYV (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_UYVY:
- vs_image_scale_4tap_UYVY (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_Y:
- case GST_VIDEO_SCALE_GRAY8:
- vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_GRAY16:
- vs_image_scale_4tap_Y16 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_I420:
- case GST_VIDEO_SCALE_YV12:
- vs_image_scale_4tap_Y (dest, src, videoscale->tmp_buf);
- vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
- vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB565:
- vs_image_scale_4tap_RGB565 (dest, src, videoscale->tmp_buf);
- break;
- case GST_VIDEO_SCALE_RGB555:
- vs_image_scale_4tap_RGB555 (dest, src, videoscale->tmp_buf);
- break;
- default:
- goto unsupported;
+
+ if (videoscale->to_height % 2 == 1) {
+ dest.height += 1;
}
- break;
- default:
- goto unknown_mode;
+ } else if (step == 1 && interlaced) {
+ src.pixels += (src.stride / 2);
+ dest.pixels += (dest.stride / 2);
+ }
+
+ switch (method) {
+ case GST_VIDEO_SCALE_NEAREST:
+ GST_LOG_OBJECT (videoscale, "doing nearest scaling");
+ switch (videoscale->format) {
+ case GST_VIDEO_SCALE_RGBx:
+ case GST_VIDEO_SCALE_xRGB:
+ case GST_VIDEO_SCALE_BGRx:
+ case GST_VIDEO_SCALE_xBGR:
+ case GST_VIDEO_SCALE_RGBA:
+ case GST_VIDEO_SCALE_ARGB:
+ case GST_VIDEO_SCALE_BGRA:
+ case GST_VIDEO_SCALE_ABGR:
+ case GST_VIDEO_SCALE_AYUV:
+ vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB:
+ case GST_VIDEO_SCALE_BGR:
+ case GST_VIDEO_SCALE_v308:
+ vs_image_scale_nearest_RGB (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_YUY2:
+ case GST_VIDEO_SCALE_YVYU:
+ vs_image_scale_nearest_YUYV (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_UYVY:
+ vs_image_scale_nearest_UYVY (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_Y:
+ case GST_VIDEO_SCALE_GRAY8:
+ vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_GRAY16:
+ vs_image_scale_nearest_Y16 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_I420:
+ case GST_VIDEO_SCALE_YV12:
+ vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf);
+ vs_image_scale_nearest_Y (&dest_u, &src_u, videoscale->tmp_buf);
+ vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB565:
+ vs_image_scale_nearest_RGB565 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB555:
+ vs_image_scale_nearest_RGB555 (&dest, &src, videoscale->tmp_buf);
+ break;
+ default:
+ goto unsupported;
+ }
+ break;
+ case GST_VIDEO_SCALE_BILINEAR:
+ GST_LOG_OBJECT (videoscale, "doing bilinear scaling");
+ switch (videoscale->format) {
+ case GST_VIDEO_SCALE_RGBx:
+ case GST_VIDEO_SCALE_xRGB:
+ case GST_VIDEO_SCALE_BGRx:
+ case GST_VIDEO_SCALE_xBGR:
+ case GST_VIDEO_SCALE_RGBA:
+ case GST_VIDEO_SCALE_ARGB:
+ case GST_VIDEO_SCALE_BGRA:
+ case GST_VIDEO_SCALE_ABGR:
+ case GST_VIDEO_SCALE_AYUV:
+ vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB:
+ case GST_VIDEO_SCALE_BGR:
+ case GST_VIDEO_SCALE_v308:
+ vs_image_scale_linear_RGB (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_YUY2:
+ case GST_VIDEO_SCALE_YVYU:
+ vs_image_scale_linear_YUYV (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_UYVY:
+ vs_image_scale_linear_UYVY (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_Y:
+ case GST_VIDEO_SCALE_GRAY8:
+ vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_GRAY16:
+ vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_I420:
+ case GST_VIDEO_SCALE_YV12:
+ vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf);
+ vs_image_scale_linear_Y (&dest_u, &src_u, videoscale->tmp_buf);
+ vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB565:
+ vs_image_scale_linear_RGB565 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB555:
+ vs_image_scale_linear_RGB555 (&dest, &src, videoscale->tmp_buf);
+ break;
+ default:
+ goto unsupported;
+ }
+ break;
+ case GST_VIDEO_SCALE_4TAP:
+ GST_LOG_OBJECT (videoscale, "doing 4tap scaling");
+ switch (videoscale->format) {
+ case GST_VIDEO_SCALE_RGBx:
+ case GST_VIDEO_SCALE_xRGB:
+ case GST_VIDEO_SCALE_BGRx:
+ case GST_VIDEO_SCALE_xBGR:
+ case GST_VIDEO_SCALE_RGBA:
+ case GST_VIDEO_SCALE_ARGB:
+ case GST_VIDEO_SCALE_BGRA:
+ case GST_VIDEO_SCALE_ABGR:
+ case GST_VIDEO_SCALE_AYUV:
+ vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB:
+ case GST_VIDEO_SCALE_BGR:
+ case GST_VIDEO_SCALE_v308:
+ vs_image_scale_4tap_RGB (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_YUY2:
+ case GST_VIDEO_SCALE_YVYU:
+ vs_image_scale_4tap_YUYV (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_UYVY:
+ vs_image_scale_4tap_UYVY (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_Y:
+ case GST_VIDEO_SCALE_GRAY8:
+ vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_GRAY16:
+ vs_image_scale_4tap_Y16 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_I420:
+ case GST_VIDEO_SCALE_YV12:
+ vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf);
+ vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf);
+ vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB565:
+ vs_image_scale_4tap_RGB565 (&dest, &src, videoscale->tmp_buf);
+ break;
+ case GST_VIDEO_SCALE_RGB555:
+ vs_image_scale_4tap_RGB555 (&dest, &src, videoscale->tmp_buf);
+ break;
+ default:
+ goto unsupported;
+ }
+ break;
+ default:
+ goto unknown_mode;
+ }
+
}
GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes",
diff --git a/gst/videoscale/gstvideoscale.h b/gst/videoscale/gstvideoscale.h
index 2024270f4..9ccb575d0 100644
--- a/gst/videoscale/gstvideoscale.h
+++ b/gst/videoscale/gstvideoscale.h
@@ -78,6 +78,7 @@ struct _GstVideoScale {
gint to_height;
gint from_width;
gint from_height;
+ gboolean interlaced;
/*< private >*/
guint8 *tmp_buf;