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,6 +270,8 @@ gst_invtelecine_compare_fields (GstInvtelecine * invtelecine, int field1,
if (j == 0 || j == invtelecine->height - 1) if (j == 0 || j == invtelecine->height - 1)
continue; continue;
if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
invtelecine->format == GST_VIDEO_FORMAT_YV12) {
data1 = GST_BUFFER_DATA (invtelecine->fifo[field1].buffer) + data1 = GST_BUFFER_DATA (invtelecine->fifo[field1].buffer) +
invtelecine->width * j; invtelecine->width * j;
data2_1 = data2_1 =
@ -279,6 +281,7 @@ gst_invtelecine_compare_fields (GstInvtelecine * invtelecine, int field1,
GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) + GST_BUFFER_DATA (invtelecine->fifo[field2].buffer) +
invtelecine->width * (j + 1); invtelecine->width * (j + 1);
/* planar 4:2:0 */
linesum = 0; linesum = 0;
for (i = 1; i < invtelecine->width - 1; i++) { for (i = 1; i < invtelecine->width - 1; i++) {
have = data1[i - 1] + data1[i + 1]; have = data1[i - 1] + data1[i + 1];
@ -288,6 +291,32 @@ gst_invtelecine_compare_fields (GstInvtelecine * invtelecine, int field1,
den = MAX (1, MAX (hdiff, vdiff)); den = MAX (1, MAX (hdiff, vdiff));
linesum += (have - vave) * (have - vave) / (den * den); 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,13 +698,18 @@ 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;
if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
invtelecine->format == GST_VIDEO_FORMAT_YV12) {
/* planar 4:2:0 */
for (j = field_index; j < height; j += 2) { for (j = field_index; j < height; j += 2) {
dest = GST_BUFFER_DATA (d) + j * width; dest = GST_BUFFER_DATA (d) + j * width;
src = GST_BUFFER_DATA (s) + j * width; src = GST_BUFFER_DATA (s) + j * width;
@ -695,6 +729,14 @@ copy_field (GstBuffer * d, GstBuffer * s, int field_index, int width,
j * width / 2; j * width / 2;
memcpy (dest, src, 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);
}
}
} }
static GstFlowReturn static GstFlowReturn
@ -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;
if (invtelecine->format == GST_VIDEO_FORMAT_I420 ||
invtelecine->format == GST_VIDEO_FORMAT_YV12) {
buffer = buffer =
gst_buffer_new_and_alloc (invtelecine->width * invtelecine->height * 3 / gst_buffer_new_and_alloc (invtelecine->width * invtelecine->height * 3 /
2); 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));