invtelecine: Add 4:2:2 formats

This commit is contained in:
David Schleef 2010-05-22 11:30:54 -07:00
parent 750cdc912b
commit c439a6bc36

View file

@ -92,7 +92,7 @@ static GstStaticPadTemplate gst_invtelecine_src_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{YUY2,UYVY,I420,YV12}")
) )
); );
@ -100,7 +100,7 @@ static GstStaticPadTemplate gst_invtelecine_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK, GST_PAD_SINK,
GST_PAD_ALWAYS, GST_PAD_ALWAYS,
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420") GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{YUY2,UYVY,I420,YV12}")
) )
); );
@ -270,23 +270,52 @@ gst_invtelecine_compare_fields (GstInvtelecine * invtelecine, int field1,
if (j == 0 || j == invtelecine->height - 1) if (j == 0 || j == invtelecine->height - 1)
continue; continue;
data1 = GST_BUFFER_DATA (invtelecine->fifo[field1].buffer) + if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
invtelecine->width * j; invtelecine->format == GST_VIDEO_FORMAT_YV12) {
data2_1 = data1 = GST_BUFFER_DATA (invtelecine->fifo[field1].buffer) +
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) + invtelecine->width * j;
invtelecine->width * (j - 1); data2_1 =
data2_2 = GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) +
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) + invtelecine->width * (j - 1);
invtelecine->width * (j + 1); data2_2 =
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) +
invtelecine->width * (j + 1);
linesum = 0; /* planar 4:2:0 */
for (i = 1; i < invtelecine->width - 1; i++) { linesum = 0;
have = data1[i - 1] + data1[i + 1]; for (i = 1; i < invtelecine->width - 1; i++) {
hdiff = abs (data1[i - 1] - data1[i + 1]); have = data1[i - 1] + data1[i + 1];
vave = data2_1[i] + data2_2[i]; hdiff = abs (data1[i - 1] - data1[i + 1]);
vdiff = abs (data2_1[i] - data2_2[i]); vave = data2_1[i] + data2_2[i];
den = MAX (1, MAX (hdiff, vdiff)); vdiff = abs (data2_1[i] - data2_2[i]);
linesum += (have - vave) * (have - vave) / (den * den); den = MAX (1, MAX (hdiff, vdiff));
linesum += (have - vave) * (have - vave) / (den * den);
}
} else {
data1 = GST_BUFFER_DATA (invtelecine->fifo[field1].buffer) +
invtelecine->width * 2 * j;
data2_1 =
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) +
invtelecine->width * 2 * (j - 1);
data2_2 =
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) +
invtelecine->width * 2 * (j + 1);
if (invtelecine->format == GST_VIDEO_FORMAT_UYVY) {
data1++;
data2_1++;
data2_2++;
}
/* packed 4:2:2 */
linesum = 0;
for (i = 1; i < invtelecine->width - 1; i++) {
have = data1[(i - 1) * 2] + data1[(i + 1) * 2];
hdiff = abs (data1[(i - 1) * 2] - data1[(i + 1) * 2]);
vave = data2_1[i * 2] + data2_2[i * 2];
vdiff = abs (data2_1[i * 2] - data2_2[i * 2]);
den = MAX (1, MAX (hdiff, vdiff));
linesum += (have - vave) * (have - vave) / (den * den);
}
} }
sum += linesum; sum += linesum;
} }
@ -669,31 +698,44 @@ gst_invtelecine_process (GstInvtelecine * invtelecine, gboolean flush)
} }
static void static void
copy_field (GstBuffer * d, GstBuffer * s, int field_index, int width, copy_field (GstInvtelecine * invtelecine, GstBuffer * d, GstBuffer * s,
int height) int field_index)
{ {
int j; int j;
guint8 *dest; guint8 *dest;
guint8 *src; guint8 *src;
int width = invtelecine->width;
int height = invtelecine->height;
for (j = field_index; j < height; j += 2) { if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
dest = GST_BUFFER_DATA (d) + j * width; invtelecine->format == GST_VIDEO_FORMAT_YV12) {
src = GST_BUFFER_DATA (s) + j * width; /* planar 4:2:0 */
memcpy (dest, src, width); for (j = field_index; j < height; j += 2) {
} dest = GST_BUFFER_DATA (d) + j * width;
for (j = field_index; j < height / 2; j += 2) { src = GST_BUFFER_DATA (s) + j * width;
dest = GST_BUFFER_DATA (d) + width * height + j * width / 2; memcpy (dest, src, width);
src = GST_BUFFER_DATA (s) + width * height + j * width / 2; }
memcpy (dest, src, width / 2); for (j = field_index; j < height / 2; j += 2) {
} dest = GST_BUFFER_DATA (d) + width * height + j * width / 2;
for (j = field_index; j < height / 2; j += 2) { src = GST_BUFFER_DATA (s) + width * height + j * width / 2;
dest = memcpy (dest, src, width / 2);
GST_BUFFER_DATA (d) + width * height + width / 2 * height / 2 + }
j * width / 2; for (j = field_index; j < height / 2; j += 2) {
src = dest =
GST_BUFFER_DATA (s) + width * height + width / 2 * height / 2 + GST_BUFFER_DATA (d) + width * height + width / 2 * height / 2 +
j * width / 2; j * width / 2;
memcpy (dest, src, width / 2); src =
GST_BUFFER_DATA (s) + width * height + width / 2 * height / 2 +
j * width / 2;
memcpy (dest, src, width / 2);
}
} else {
/* packed 4:2:2 */
for (j = field_index; j < height; j += 2) {
dest = GST_BUFFER_DATA (d) + j * width * 2;
src = GST_BUFFER_DATA (s) + j * width * 2;
memcpy (dest, src, width * 2);
}
} }
} }
@ -705,14 +747,19 @@ gst_invtelecine_output_fields (GstInvtelecine * invtelecine, int num_fields)
field_index = invtelecine->fifo[0].field_index; field_index = invtelecine->fifo[0].field_index;
buffer = if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
gst_buffer_new_and_alloc (invtelecine->width * invtelecine->height * 3 / invtelecine->format == GST_VIDEO_FORMAT_YV12) {
2); buffer =
gst_buffer_new_and_alloc (invtelecine->width * invtelecine->height * 3 /
2);
} else {
buffer =
gst_buffer_new_and_alloc (invtelecine->width * invtelecine->height * 2);
}
copy_field (buffer, invtelecine->fifo[0].buffer, field_index, copy_field (invtelecine, buffer, invtelecine->fifo[0].buffer, field_index);
invtelecine->width, invtelecine->height); copy_field (invtelecine, buffer, invtelecine->fifo[1].buffer,
copy_field (buffer, invtelecine->fifo[1].buffer, field_index ^ 1, field_index ^ 1);
invtelecine->width, invtelecine->height);
gst_buffer_set_caps (buffer, GST_BUFFER_CAPS (invtelecine->fifo[0].buffer)); gst_buffer_set_caps (buffer, GST_BUFFER_CAPS (invtelecine->fifo[0].buffer));