fieldanalysis: Use RFF flag to indicate buffers to drop downstream

Use of the GAP flag is not really correct here and makes it difficult to
handle real GAP buffers in deinterlace. The RFF flag is unused and can
be reused with similar semantics - the buffers marked with RFF that are
in a telecine state contain only unneeded repeated fields and so can be
dropped.
This commit is contained in:
Robert Swain 2011-04-06 15:58:07 +02:00
parent a34108899e
commit 4cd15193bb
2 changed files with 40 additions and 39 deletions

View file

@ -632,7 +632,7 @@ gst_field_analysis_set_caps (GstPad * pad, GstCaps * caps)
* returns it */ * returns it */
static GstBuffer * static GstBuffer *
gst_field_analysis_decorate (GstFieldAnalysis * filter, gboolean tff, gst_field_analysis_decorate (GstFieldAnalysis * filter, gboolean tff,
gboolean onefield, FieldAnalysisConclusion conclusion, gboolean gap) gboolean onefield, FieldAnalysisConclusion conclusion, gboolean drop)
{ {
GstBuffer *buf = NULL; GstBuffer *buf = NULL;
GstCaps *caps; GstCaps *caps;
@ -676,10 +676,11 @@ gst_field_analysis_decorate (GstFieldAnalysis * filter, gboolean tff,
GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_ONEFIELD); GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_ONEFIELD);
} }
GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_RFF); if (drop) {
GST_BUFFER_FLAG_SET (buf, GST_VIDEO_BUFFER_RFF);
if (gap) } else {
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP); GST_BUFFER_FLAG_UNSET (buf, GST_VIDEO_BUFFER_RFF);
}
if (conclusion == FIELD_ANALYSIS_TELECINE_PROGRESSIVE || (filter->is_telecine if (conclusion == FIELD_ANALYSIS_TELECINE_PROGRESSIVE || (filter->is_telecine
&& conclusion == FIELD_ANALYSIS_PROGRESSIVE)) && conclusion == FIELD_ANALYSIS_PROGRESSIVE))
@ -706,12 +707,12 @@ gst_field_analysis_decorate (GstFieldAnalysis * filter, gboolean tff,
gst_caps_unref (caps); gst_caps_unref (caps);
GST_DEBUG_OBJECT (filter, GST_DEBUG_OBJECT (filter,
"Pushing buffer with flags: %p (%p), p %d, tff %d, 1f %d, gap %d; conc %d", "Pushing buffer with flags: %p (%p), p %d, tff %d, 1f %d, drop %d; conc %d",
GST_BUFFER_DATA (buf), buf, GST_BUFFER_DATA (buf), buf,
GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_PROGRESSIVE), GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_PROGRESSIVE),
GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_TFF), GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_TFF),
GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_ONEFIELD), GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_ONEFIELD),
GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP), conclusion); GST_BUFFER_FLAG_IS_SET (buf, GST_VIDEO_BUFFER_RFF), conclusion);
return buf; return buf;
} }
@ -1399,7 +1400,7 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
res0->conclusion = FIELD_ANALYSIS_INTERLACED; res0->conclusion = FIELD_ANALYSIS_INTERLACED;
} }
res0->holding = -1; /* needed fields unknown */ res0->holding = -1; /* needed fields unknown */
res0->gap = FALSE; res0->drop = FALSE;
} }
if (n_queued >= 2) { if (n_queued >= 2) {
@ -1454,11 +1455,11 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* prev P, cur repeated => cur P */ /* prev P, cur repeated => cur P */
res0->conclusion = FIELD_ANALYSIS_TELECINE_PROGRESSIVE; res0->conclusion = FIELD_ANALYSIS_TELECINE_PROGRESSIVE;
res0->holding = 1 + BOTH_FIELDS; res0->holding = 1 + BOTH_FIELDS;
/* push prev P, GAP */ /* push prev P, RFF */
res1->gap = TRUE; res1->drop = TRUE;
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} else { } else {
/* prev P, cur t xor b matches => cur TCM */ /* prev P, cur t xor b matches => cur TCM */
res0->conclusion = FIELD_ANALYSIS_TELECINE_MIXED; res0->conclusion = FIELD_ANALYSIS_TELECINE_MIXED;
@ -1467,7 +1468,7 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push prev P */ /* push prev P */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} }
} else { } else {
/* prev !P */ /* prev !P */
@ -1508,7 +1509,7 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push 1F held field */ /* push 1F held field */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else if (res0->f > filter->frame_thresh && ((t } else if (res0->f > filter->frame_thresh && ((t
&& telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP) || (b && telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP) || (b
&& telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM))) { && telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM))) {
@ -1523,7 +1524,7 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push 1F held field */ /* push 1F held field */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else if (first_buffer && (telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP } else if (first_buffer && (telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP
|| telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM)) { || telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM)) {
/* non-matched field is an orphan in the first buffer - push orphan as 1F */ /* non-matched field is an orphan in the first buffer - push orphan as 1F */
@ -1533,18 +1534,18 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push 1F held field */ /* push 1F held field */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else if (res1->holding == 1 + BOTH_FIELDS || res1->holding == -1) { } else if (res1->holding == 1 + BOTH_FIELDS || res1->holding == -1) {
/* holding both fields, push prev as is */ /* holding both fields, push prev as is */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} else { } else {
/* push prev as is with GAP */ /* push prev as is with RFF */
res1->gap = TRUE; res1->drop = TRUE;
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} }
} }
} else if (res0->f <= filter->frame_thresh) { } else if (res0->f <= filter->frame_thresh) {
@ -1555,19 +1556,19 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* holding both fields, push prev as is */ /* holding both fields, push prev as is */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} else if (res1->holding > 0) { } else if (res1->holding > 0) {
/* holding one field, push prev 1F held */ /* holding one field, push prev 1F held */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else { } else {
/* unknown or no fields held, push prev as is with GAP */ /* unknown or no fields held, push prev as is with RFF */
/* this will push unknown as gap - should be pushed as not gap? */ /* this will push unknown as drop - should be pushed as not drop? */
res1->gap = TRUE; res1->drop = TRUE;
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} }
} else { } else {
/* cur !P */ /* cur !P */
@ -1590,7 +1591,7 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push prev as is */ /* push prev as is */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} else if ((t && telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM) || (b } else if ((t && telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM) || (b
&& telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP)) { && telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP)) {
/* held is opposite to matched => need both field from prev */ /* held is opposite to matched => need both field from prev */
@ -1600,47 +1601,47 @@ gst_field_analysis_process_buffer (GstFieldAnalysis * filter,
/* push prev TCM */ /* push prev TCM */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} else if ((res1->holding > 0 && res1->holding != 1 + BOTH_FIELDS) || (t } else if ((res1->holding > 0 && res1->holding != 1 + BOTH_FIELDS) || (t
&& telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP) || (b && telecine_matches & FIELD_ANALYSIS_BOTTOM_TOP) || (b
&& telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM)) { && telecine_matches & FIELD_ANALYSIS_TOP_BOTTOM)) {
/* held field is needed, push prev 1F held */ /* held field is needed, push prev 1F held */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else { } else {
/* holding none or unknown */ /* holding none or unknown */
/* push prev as is with GAP */ /* push prev as is with RFF */
res1->gap = TRUE; res1->drop = TRUE;
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} }
} else { } else {
/* cur I */ /* cur I */
res0->conclusion = FIELD_ANALYSIS_INTERLACED; res0->conclusion = FIELD_ANALYSIS_INTERLACED;
res0->holding = 1 + BOTH_FIELDS; res0->holding = 1 + BOTH_FIELDS;
/* push prev appropriately */ /* push prev appropriately */
res1->gap = res1->holding <= 0; res1->drop = res1->holding <= 0;
if (res1->holding != 0) { if (res1->holding != 0) {
res1->gap = FALSE; res1->drop = FALSE;
if (res1->holding == 1 + BOTH_FIELDS || res1->holding == -1) { if (res1->holding == 1 + BOTH_FIELDS || res1->holding == -1) {
/* push prev as is */ /* push prev as is */
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, gst_field_analysis_decorate (filter, -1, FALSE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} else { } else {
/* push prev 1F held */ /* push prev 1F held */
outbuf = outbuf =
gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE, gst_field_analysis_decorate (filter, !(res1->holding - 1), TRUE,
res1->conclusion, res1->gap); res1->conclusion, res1->drop);
} }
} else { } else {
/* push prev as is with GAP */ /* push prev as is with RFF */
res1->gap = TRUE; res1->drop = TRUE;
outbuf = outbuf =
gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion, gst_field_analysis_decorate (filter, -1, FALSE, res1->conclusion,
res1->gap); res1->drop);
} }
} }
} }

View file

@ -91,7 +91,7 @@ struct _FieldAnalysis
FieldAnalysisConclusion conclusion; FieldAnalysisConclusion conclusion;
/* -1 - unknown; 0 - holding none; 1 - top field; 2 - bottom field; 3 - both */ /* -1 - unknown; 0 - holding none; 1 - top field; 2 - bottom field; 3 - both */
gint holding; gint holding;
gboolean gap; gboolean drop;
}; };
typedef enum typedef enum