From b3d96e06c6d9df3679cb9a7036bb3b226cb56aff Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Mon, 3 Feb 2020 13:08:39 +0530 Subject: [PATCH] deinterlace: add wrapper to get field lines from history No semantic change so far, will be used to implement alternate support. --- gst/deinterlace/gstdeinterlacemethod.c | 166 +++++++++++++++++---------------- 1 file changed, 85 insertions(+), 81 deletions(-) diff --git a/gst/deinterlace/gstdeinterlacemethod.c b/gst/deinterlace/gstdeinterlacemethod.c index d7320e6..60105b8 100644 --- a/gst/deinterlace/gstdeinterlacemethod.c +++ b/gst/deinterlace/gstdeinterlacemethod.c @@ -304,6 +304,41 @@ gst_deinterlace_simple_method_copy_scanline_packed (GstDeinterlaceSimpleMethod * memcpy (out, scanlines->m0, stride); } +typedef struct +{ + const GstDeinterlaceField *history; + guint history_count; + gint cur_field_idx; +} LinesGetter; + +#define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i)) +#define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i)) + +static guint8 * +get_line (LinesGetter * lg, gint field_offset, guint plane, gint line, + gint line_offset) +{ + const GstVideoFrame *frame; + gint idx, frame_height; + guint8 *data; + + idx = lg->cur_field_idx + field_offset; + if (idx < 0 || idx >= lg->history_count) + return NULL; + + frame = lg->history[idx].frame; + g_assert (frame); + + frame_height = GST_VIDEO_FRAME_COMP_HEIGHT (frame, plane); + line += line_offset; + + data = GST_VIDEO_FRAME_PLANE_DATA ((frame), plane); + data += CLAMP_HI (CLAMP_LOW (line)) * GST_VIDEO_FRAME_PLANE_STRIDE ((frame), + plane); + + return data; +} + static void gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * method, const GstDeinterlaceField * history, guint history_count, @@ -317,6 +352,7 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * guint cur_field_flags; gint i; gint frame_height, frame_width; + LinesGetter lg = { history, history_count, cur_field_idx }; GstVideoFrame *framep, *frame0, *frame1, *frame2; g_assert (self->interpolate_scanline_packed != NULL); @@ -347,11 +383,8 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * if (frame2) frame_width = MIN (frame_width, GST_VIDEO_FRAME_PLANE_STRIDE (frame2, 0)); -#define CLAMP_LOW(i) (((i)<0) ? (i+2) : (i)) -#define CLAMP_HI(i) (((i)>=(frame_height)) ? (i-2) : (i)) -#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),0)) + CLAMP_HI(CLAMP_LOW(i)) * \ +#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),0)) + i * \ GST_VIDEO_FRAME_PLANE_STRIDE((x),0)) -#define LINE2(x,i) ((x) ? LINE(x,i) : NULL) for (i = 0; i < frame_height; i++) { memset (&scanlines, 0, sizeof (scanlines)); @@ -359,43 +392,42 @@ gst_deinterlace_simple_method_deinterlace_frame_packed (GstDeinterlaceMethod * if (!((i & 1) ^ scanlines.bottom_field)) { /* copying */ - scanlines.tp = LINE2 (framep, i - 1); - scanlines.bp = LINE2 (framep, i + 1); + scanlines.tp = get_line (&lg, -1, 0, i, -1); + scanlines.bp = get_line (&lg, -1, 0, i, 1); - scanlines.tt0 = LINE2 (frame0, i - 2); - scanlines.m0 = LINE2 (frame0, i); - scanlines.bb0 = LINE2 (frame0, i + 2); + scanlines.tt0 = get_line (&lg, 0, 0, i, -2); + scanlines.m0 = get_line (&lg, 0, 0, i, 0); + scanlines.bb0 = get_line (&lg, 0, 0, i, 2); - scanlines.t1 = LINE2 (frame1, i - 1); - scanlines.b1 = LINE2 (frame1, i + 1); + scanlines.t1 = get_line (&lg, 1, 0, i, -1); + scanlines.b1 = get_line (&lg, 1, 0, i, 1); - scanlines.tt2 = LINE2 (frame2, i - 2); - scanlines.m2 = LINE2 (frame2, i); - scanlines.bb2 = LINE2 (frame2, i + 2); + scanlines.tt2 = get_line (&lg, 2, 0, i, -2); + scanlines.m2 = get_line (&lg, 2, 0, i, 0); + scanlines.bb2 = get_line (&lg, 2, 0, i, 2); self->copy_scanline_packed (self, LINE (outframe, i), &scanlines, frame_width); } else { /* interpolating */ - scanlines.ttp = LINE2 (framep, i - 2); - scanlines.mp = LINE2 (framep, i); - scanlines.bbp = LINE2 (framep, i + 2); + scanlines.ttp = get_line (&lg, -1, 0, i, -2); + scanlines.mp = get_line (&lg, -1, 0, i, 0); + scanlines.bbp = get_line (&lg, -1, 0, i, 2); - scanlines.t0 = LINE2 (frame0, i - 1); - scanlines.b0 = LINE2 (frame0, i + 1); + scanlines.t0 = get_line (&lg, 0, 0, i, -1); + scanlines.b0 = get_line (&lg, 0, 0, i, 1); - scanlines.tt1 = LINE2 (frame1, i - 2); - scanlines.m1 = LINE2 (frame1, i); - scanlines.bb1 = LINE2 (frame1, i + 2); + scanlines.tt1 = get_line (&lg, 1, 0, i, -2); + scanlines.m1 = get_line (&lg, 1, 0, i, 0); + scanlines.bb1 = get_line (&lg, 1, 0, i, 2); - scanlines.t2 = LINE2 (frame2, i - 1); - scanlines.b2 = LINE2 (frame2, i + 1); + scanlines.t2 = get_line (&lg, 2, 0, i, -1); + scanlines.b2 = get_line (&lg, 2, 0, i, 1); self->interpolate_scanline_packed (self, LINE (outframe, i), &scanlines, frame_width); } #undef LINE -#undef LINE2 } } @@ -450,8 +482,7 @@ gst_deinterlace_simple_method_copy_scanline_planar_v (GstDeinterlaceSimpleMethod static void gst_deinterlace_simple_method_deinterlace_frame_planar_plane (GstDeinterlaceSimpleMethod * self, GstVideoFrame * dest, - const GstVideoFrame * frame0, const GstVideoFrame * frame1, - const GstVideoFrame * frame2, const GstVideoFrame * framep, + LinesGetter * lg, guint cur_field_flags, gint plane, GstDeinterlaceSimpleMethodFunction copy_scanline, GstDeinterlaceSimpleMethodFunction interpolate_scanline) @@ -467,9 +498,8 @@ static void g_assert (interpolate_scanline != NULL); g_assert (copy_scanline != NULL); -#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),plane)) + CLAMP_HI(CLAMP_LOW(i)) * \ +#define LINE(x,i) (((guint8*)GST_VIDEO_FRAME_PLANE_DATA((x),plane)) + i * \ GST_VIDEO_FRAME_PLANE_STRIDE((x),plane)) -#define LINE2(x,i) ((x) ? LINE(x,i) : NULL) for (i = 0; i < frame_height; i++) { memset (&scanlines, 0, sizeof (scanlines)); @@ -477,41 +507,40 @@ static void if (!((i & 1) ^ scanlines.bottom_field)) { /* copying */ - scanlines.tp = LINE2 (framep, i - 1); - scanlines.bp = LINE2 (framep, i + 1); + scanlines.tp = get_line (lg, -1, plane, i, -1); + scanlines.bp = get_line (lg, -1, plane, i, 1); - scanlines.tt0 = LINE2 (frame0, i - 2); - scanlines.m0 = LINE2 (frame0, i); - scanlines.bb0 = LINE2 (frame0, i + 2); + scanlines.tt0 = get_line (lg, 0, plane, i, -2); + scanlines.m0 = get_line (lg, 0, plane, i, 0); + scanlines.bb0 = get_line (lg, 0, plane, i, 2); - scanlines.t1 = LINE2 (frame1, i - 1); - scanlines.b1 = LINE2 (frame1, i + 1); + scanlines.t1 = get_line (lg, 1, plane, i, -1); + scanlines.b1 = get_line (lg, 1, plane, i, 1); - scanlines.tt2 = LINE2 (frame2, i - 2); - scanlines.m2 = LINE2 (frame2, i); - scanlines.bb2 = LINE2 (frame2, i + 2); + scanlines.tt2 = get_line (lg, 2, plane, i, -2); + scanlines.m2 = get_line (lg, 2, plane, i, 0); + scanlines.bb2 = get_line (lg, 2, plane, i, 2); copy_scanline (self, LINE (dest, i), &scanlines, frame_width); } else { /* interpolating */ - scanlines.ttp = LINE2 (framep, i - 2); - scanlines.mp = LINE2 (framep, i); - scanlines.bbp = LINE2 (framep, i + 2); + scanlines.ttp = get_line (lg, -1, plane, i, -2); + scanlines.mp = get_line (lg, -1, plane, i, 0); + scanlines.bbp = get_line (lg, -1, plane, i, 2); - scanlines.t0 = LINE2 (frame0, i - 1); - scanlines.b0 = LINE2 (frame0, i + 1); + scanlines.t0 = get_line (lg, 0, plane, i, -1); + scanlines.b0 = get_line (lg, 0, plane, i, 1); - scanlines.tt1 = LINE2 (frame1, i - 2); - scanlines.m1 = LINE2 (frame1, i); - scanlines.bb1 = LINE2 (frame1, i + 2); + scanlines.tt1 = get_line (lg, 1, plane, i, -2); + scanlines.m1 = get_line (lg, 1, plane, i, 0); + scanlines.bb1 = get_line (lg, 1, plane, i, 2); - scanlines.t2 = LINE2 (frame2, i - 1); - scanlines.b2 = LINE2 (frame2, i + 1); + scanlines.t2 = get_line (lg, 2, plane, i, -1); + scanlines.b2 = get_line (lg, 2, plane, i, 1); interpolate_scanline (self, LINE (dest, i), &scanlines, frame_width); } #undef LINE -#undef LINE2 } } @@ -524,11 +553,11 @@ gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * #ifndef G_DISABLE_ASSERT GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); #endif - const GstVideoFrame *frame0, *frame1, *frame2, *framep; guint cur_field_flags = history[cur_field_idx].flags; gint i; GstDeinterlaceSimpleMethodFunction copy_scanline; GstDeinterlaceSimpleMethodFunction interpolate_scanline; + LinesGetter lg = { history, history_count, cur_field_idx }; g_assert (self->interpolate_scanline_planar[0] != NULL); g_assert (self->interpolate_scanline_planar[1] != NULL); @@ -536,27 +565,14 @@ gst_deinterlace_simple_method_deinterlace_frame_planar (GstDeinterlaceMethod * g_assert (self->copy_scanline_planar[0] != NULL); g_assert (self->copy_scanline_planar[1] != NULL); g_assert (self->copy_scanline_planar[2] != NULL); + g_assert (dm_class->fields_required <= 4); for (i = 0; i < 3; i++) { copy_scanline = self->copy_scanline_planar[i]; interpolate_scanline = self->interpolate_scanline_planar[i]; - framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL); - - frame0 = history[cur_field_idx].frame; - - g_assert (dm_class->fields_required <= 4); - - frame1 = - (cur_field_idx + 1 < - history_count ? history[cur_field_idx + 1].frame : NULL); - frame2 = - (cur_field_idx + 2 < - history_count ? history[cur_field_idx + 2].frame : NULL); - gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, - outframe, frame0, frame1, frame2, framep, cur_field_flags, i, - copy_scanline, interpolate_scanline); + outframe, &lg, cur_field_flags, i, copy_scanline, interpolate_scanline); } } @@ -569,29 +585,17 @@ gst_deinterlace_simple_method_deinterlace_frame_nv12 (GstDeinterlaceMethod * #ifndef G_DISABLE_ASSERT GstDeinterlaceMethodClass *dm_class = GST_DEINTERLACE_METHOD_GET_CLASS (self); #endif - const GstVideoFrame *frame0, *frame1, *frame2, *framep; guint cur_field_flags = history[cur_field_idx].flags; gint i; + LinesGetter lg = { history, history_count, cur_field_idx, }; g_assert (self->interpolate_scanline_packed != NULL); g_assert (self->copy_scanline_packed != NULL); + g_assert (dm_class->fields_required <= 4); for (i = 0; i < 2; i++) { - framep = (cur_field_idx > 0 ? history[cur_field_idx - 1].frame : NULL); - - frame0 = history[cur_field_idx].frame; - - g_assert (dm_class->fields_required <= 4); - - frame1 = - (cur_field_idx + 1 < - history_count ? history[cur_field_idx + 1].frame : NULL); - frame2 = - (cur_field_idx + 2 < - history_count ? history[cur_field_idx + 2].frame : NULL); - gst_deinterlace_simple_method_deinterlace_frame_planar_plane (self, - outframe, frame0, frame1, frame2, framep, cur_field_flags, i, + outframe, &lg, cur_field_flags, i, self->copy_scanline_packed, self->interpolate_scanline_packed); } } -- 2.7.4