gst/videocrop/gstvideocrop.*: Handle packed YUV formats (UYVY, YUY2, YUYV) separately; also, fix passthrough mode; la...

Original commit message from CVS:
* gst/videocrop/gstvideocrop.c: (gst_video_crop_class_init),
(gst_video_crop_init),
(gst_video_crop_get_image_details_from_caps),
(gst_video_crop_transform_packed_complex),
(gst_video_crop_transform_packed_simple),
(gst_video_crop_transform), (gst_video_crop_transform_caps),
(gst_video_crop_set_caps),
(gst_videocrop_clear_negotiated_caps_locked),
(gst_video_crop_set_property):
* gst/videocrop/gstvideocrop.h:
Handle packed YUV formats (UYVY, YUY2, YUYV) separately; also, fix
passthrough mode; lastly, clear negotiated basetransform caps when
the cropping changes in order to force renegotiation.
This commit is contained in:
Tim-Philipp Müller 2006-10-04 22:37:07 +00:00
parent 425c1eecbf
commit ec674dcbdf
3 changed files with 133 additions and 18 deletions

View file

@ -1,3 +1,19 @@
2006-10-04 Tim-Philipp Müller <tim at centricular dot net>
* gst/videocrop/gstvideocrop.c: (gst_video_crop_class_init),
(gst_video_crop_init),
(gst_video_crop_get_image_details_from_caps),
(gst_video_crop_transform_packed_complex),
(gst_video_crop_transform_packed_simple),
(gst_video_crop_transform), (gst_video_crop_transform_caps),
(gst_video_crop_set_caps),
(gst_videocrop_clear_negotiated_caps_locked),
(gst_video_crop_set_property):
* gst/videocrop/gstvideocrop.h:
Handle packed YUV formats (UYVY, YUY2, YUYV) separately; also, fix
passthrough mode; lastly, clear negotiated basetransform caps when
the cropping changes in order to force renegotiation.
2006-10-04 Tim-Philipp Müller <tim at centricular dot net> 2006-10-04 Tim-Philipp Müller <tim at centricular dot net>
* tests/icles/.cvsignore: * tests/icles/.cvsignore:

View file

@ -183,7 +183,7 @@ gst_video_crop_class_init (GstVideoCropClass * klass)
basetransform_class->get_unit_size = basetransform_class->get_unit_size =
GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size); GST_DEBUG_FUNCPTR (gst_video_crop_get_unit_size);
basetransform_class->passthrough_on_same_caps = TRUE; basetransform_class->passthrough_on_same_caps = FALSE;
} }
static void static void
@ -194,6 +194,7 @@ gst_video_crop_init (GstVideoCrop * vcrop, GstVideoCropClass * klass)
vcrop->crop_top = 0; vcrop->crop_top = 0;
vcrop->crop_bottom = 0; vcrop->crop_bottom = 0;
vcrop->noop = TRUE; vcrop->noop = TRUE;
GST_BASE_TRANSFORM (vcrop)->passthrough = vcrop->noop;
} }
static gboolean static gboolean
@ -218,7 +219,7 @@ gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop,
if (!gst_structure_get_int (structure, "bpp", &bpp) || (bpp & 0x07) != 0) if (!gst_structure_get_int (structure, "bpp", &bpp) || (bpp & 0x07) != 0)
goto incomplete_format; goto incomplete_format;
details->packed = TRUE; details->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE;
details->bytes_per_pixel = bpp / 8; details->bytes_per_pixel = bpp / 8;
details->stride = GST_ROUND_UP_4 (width * details->bytes_per_pixel); details->stride = GST_ROUND_UP_4 (width * details->bytes_per_pixel);
details->size = details->stride * height; details->size = details->stride * height;
@ -230,7 +231,7 @@ gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop,
switch (format) { switch (format) {
case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'): case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'):
details->packed = TRUE; details->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE;
details->bytes_per_pixel = 4; details->bytes_per_pixel = 4;
details->stride = GST_ROUND_UP_4 (width * 4); details->stride = GST_ROUND_UP_4 (width * 4);
details->size = details->stride * height; details->size = details->stride * height;
@ -238,20 +239,25 @@ gst_video_crop_get_image_details_from_caps (GstVideoCrop * vcrop,
case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
details->packed = TRUE; details->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX;
details->bytes_per_pixel = 2; details->bytes_per_pixel = 2;
details->stride = GST_ROUND_UP_4 (width * 2); details->stride = GST_ROUND_UP_4 (width * 2);
details->size = details->stride * height; details->size = details->stride * height;
if (format == GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y')) {
details->macro_y_off = 1;
} else {
details->macro_y_off = 0;
}
break; break;
case GST_MAKE_FOURCC ('Y', '8', '0', '0'): case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
details->packed = TRUE; details->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE;
details->bytes_per_pixel = 1; details->bytes_per_pixel = 1;
details->stride = GST_ROUND_UP_4 (width); details->stride = GST_ROUND_UP_4 (width);
details->size = details->stride * height; details->size = details->stride * height;
break; break;
case GST_MAKE_FOURCC ('I', '4', '2', '0'): case GST_MAKE_FOURCC ('I', '4', '2', '0'):
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):{ case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):{
details->packed = FALSE; details->packing = VIDEO_CROP_PIXEL_FORMAT_PLANAR;
details->y_stride = GST_ROUND_UP_4 (width); details->y_stride = GST_ROUND_UP_4 (width);
details->u_stride = GST_ROUND_UP_8 (width) / 2; details->u_stride = GST_ROUND_UP_8 (width) / 2;
@ -306,8 +312,53 @@ gst_video_crop_get_unit_size (GstBaseTransform * trans, GstCaps * caps,
} }
static void static void
gst_video_crop_transform_packed (GstVideoCrop * vcrop, GstBuffer * inbuf, gst_video_crop_transform_packed_complex (GstVideoCrop * vcrop,
GstBuffer * outbuf) GstBuffer * inbuf, GstBuffer * outbuf)
{
guint8 *in_data, *out_data;
guint i, dx;
in_data = GST_BUFFER_DATA (inbuf);
out_data = GST_BUFFER_DATA (outbuf);
in_data += vcrop->crop_top * vcrop->in.stride;
in_data += vcrop->crop_left * vcrop->in.bytes_per_pixel;
dx = vcrop->out.width * vcrop->out.bytes_per_pixel;
if ((vcrop->crop_left % 2) != 0) {
for (i = 0; i < vcrop->out.height; ++i) {
gint j;
memcpy (out_data, in_data, dx);
/* U/V is horizontally subsampled by a factor of 2, so must fix that up */
/* FIXME: this is obviously not quite right */
if (vcrop->in.macro_y_off == 0) {
for (j = 1; j < vcrop->out.stride; j += 2) {
out_data[j] = in_data[j - 1];
}
} else {
for (j = 0; j < vcrop->out.stride /* -2 */ ; j += 2) {
out_data[j] = in_data[j + 2];
}
}
in_data += vcrop->in.stride;
out_data += vcrop->out.stride;
}
} else {
for (i = 0; i < vcrop->out.height; ++i) {
memcpy (out_data, in_data, dx);
in_data += vcrop->in.stride;
out_data += vcrop->out.stride;
}
}
}
static void
gst_video_crop_transform_packed_simple (GstVideoCrop * vcrop,
GstBuffer * inbuf, GstBuffer * outbuf)
{ {
guint8 *in_data, *out_data; guint8 *in_data, *out_data;
guint i, dx; guint i, dx;
@ -390,10 +441,18 @@ gst_video_crop_transform (GstBaseTransform * trans, GstBuffer * inbuf,
goto cropping_too_much; goto cropping_too_much;
} }
if (vcrop->in.packed) { switch (vcrop->in.packing) {
gst_video_crop_transform_packed (vcrop, inbuf, outbuf); case VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE:
} else { gst_video_crop_transform_packed_simple (vcrop, inbuf, outbuf);
gst_video_crop_transform_planar (vcrop, inbuf, outbuf); break;
case VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX:
gst_video_crop_transform_packed_complex (vcrop, inbuf, outbuf);
break;
case VIDEO_CROP_PIXEL_FORMAT_PLANAR:
gst_video_crop_transform_planar (vcrop, inbuf, outbuf);
break;
default:
g_assert_not_reached ();
} }
GST_OBJECT_UNLOCK (vcrop); GST_OBJECT_UNLOCK (vcrop);
@ -474,10 +533,17 @@ gst_video_crop_transform_caps (GstBaseTransform * trans,
vcrop = GST_VIDEO_CROP (trans); vcrop = GST_VIDEO_CROP (trans);
if (vcrop->noop)
return gst_caps_ref (caps);
GST_OBJECT_LOCK (vcrop); GST_OBJECT_LOCK (vcrop);
GST_LOG_OBJECT (vcrop, "l=%d,r=%d,b=%d,t=%d noop=%d",
vcrop->crop_left, vcrop->crop_right, vcrop->crop_bottom,
vcrop->crop_top, vcrop->noop);
if (vcrop->noop) {
GST_OBJECT_UNLOCK (vcrop);
return gst_caps_ref (caps);
}
if (direction == GST_PAD_SRC) { if (direction == GST_PAD_SRC) {
dx = vcrop->crop_left + vcrop->crop_right; dx = vcrop->crop_left + vcrop->crop_right;
dy = vcrop->crop_top + vcrop->crop_bottom; dy = vcrop->crop_top + vcrop->crop_bottom;
@ -550,9 +616,29 @@ gst_video_crop_set_caps (GstBaseTransform * trans, GstCaps * incaps,
return FALSE; return FALSE;
} }
GST_LOG_OBJECT (crop, "incaps = %" GST_PTR_FORMAT ", outcaps = %"
GST_PTR_FORMAT, incaps, outcaps);
return TRUE; return TRUE;
} }
/* This is extremely hackish, but the only way to force basetransform to
* renegotiated at the moment. There should really be a basetransform
* function for this */
static void
gst_videocrop_clear_negotiated_caps_locked (GstVideoCrop * crop)
{
GST_LOG_OBJECT (crop, "clearing negotiated caps");
GST_BASE_TRANSFORM (crop)->negotiated = FALSE;
gst_caps_replace (&GST_PAD_CAPS (GST_BASE_TRANSFORM (crop)->srcpad), NULL);
gst_caps_replace (&GST_PAD_CAPS (GST_BASE_TRANSFORM (crop)->sinkpad), NULL);
gst_caps_replace (&GST_BASE_TRANSFORM (crop)->cache_caps1, NULL);
GST_BASE_TRANSFORM (crop)->cache_caps1_size = 0;
gst_caps_replace (&GST_BASE_TRANSFORM (crop)->cache_caps2, NULL);
GST_BASE_TRANSFORM (crop)->cache_caps2_size = 0;
GST_LOG_OBJECT (crop, "clearing caps done");
}
static void static void
gst_video_crop_set_property (GObject * object, guint prop_id, gst_video_crop_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
@ -583,6 +669,12 @@ gst_video_crop_set_property (GObject * object, guint prop_id,
video_crop->noop = ((video_crop->crop_left | video_crop->crop_right | video_crop->noop = ((video_crop->crop_left | video_crop->crop_right |
video_crop->crop_top | video_crop->crop_bottom) == 0); video_crop->crop_top | video_crop->crop_bottom) == 0);
GST_LOG_OBJECT (video_crop, "l=%d,r=%d,b=%d,t=%d noop=%d",
video_crop->crop_left, video_crop->crop_right, video_crop->crop_bottom,
video_crop->crop_top, video_crop->noop);
GST_BASE_TRANSFORM (video_crop)->passthrough = video_crop->noop;
gst_videocrop_clear_negotiated_caps_locked (video_crop);
GST_OBJECT_UNLOCK (video_crop); GST_OBJECT_UNLOCK (video_crop);
} }

View file

@ -35,19 +35,26 @@ G_BEGIN_DECLS
#define GST_IS_VIDEO_CROP_CLASS(klass) \ #define GST_IS_VIDEO_CROP_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_CROP)) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_CROP))
typedef enum {
VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE = 0, /* RGBx, AYUV */
VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX, /* UYVY, YVYU */
VIDEO_CROP_PIXEL_FORMAT_PLANAR /* I420, YV12 */
} VideoCropPixelFormat;
typedef struct _GstVideoCropImageDetails GstVideoCropImageDetails; typedef struct _GstVideoCropImageDetails GstVideoCropImageDetails;
struct _GstVideoCropImageDetails struct _GstVideoCropImageDetails
{ {
/*< private >*/ /*< private >*/
gboolean packed; /* TRUE if packed, FALSE if planar */ VideoCropPixelFormat packing;
guint width; guint width;
guint height; guint height;
guint size; guint size;
/* for packed RGB and YUV */ /* for packed RGB and YUV */
guint stride; guint stride;
guint bytes_per_pixel; guint bytes_per_pixel;
guint8 macro_y_off; /* for YUY2, YVYU, UYVY, Y offset within macropixel in bytes */
/* for planar YUV */ /* for planar YUV */
guint y_stride, y_off; guint y_stride, y_off;