#define GST_DEINTERLACE_BUFFER_STATE_TC_T (1<<3)
#define GST_DEINTERLACE_BUFFER_STATE_TC_P (1<<4)
#define GST_DEINTERLACE_BUFFER_STATE_TC_M (1<<5)
-#define GST_DEINTERLACE_BUFFER_STATE_DROP (1<<6)
+#define GST_DEINTERLACE_BUFFER_STATE_RFF (1<<6)
#define GST_ONE \
(GST_DEINTERLACE_BUFFER_STATE_TC_T | GST_DEINTERLACE_BUFFER_STATE_TC_B)
(GST_DEINTERLACE_BUFFER_STATE_P | GST_DEINTERLACE_BUFFER_STATE_TC_P)
#define GST_INT \
(GST_DEINTERLACE_BUFFER_STATE_I | GST_DEINTERLACE_BUFFER_STATE_TC_M)
-#define GST_DRP (GST_DEINTERLACE_BUFFER_STATE_DROP)
+#define GST_RFF (GST_DEINTERLACE_BUFFER_STATE_RFF)
#define GST_DEINTERLACE_OBSCURE_THRESHOLD 5
/* 60i -> 30p or 50i -> 25p */
{"2:2", 1, 1, 1, {GST_INT,}},
/* 60i telecine -> 24p */
+ {"2:3-RFF", 4, 4, 5, {GST_PRG, GST_RFF, GST_PRG, GST_RFF,}},
{"2:3", 5, 4, 5, {GST_PRG, GST_PRG, GST_ONE, GST_ONE, GST_PRG,}},
+ {"3:2:2:3-RFF", 4, 4, 5, {GST_RFF, GST_PRG, GST_PRG, GST_RFF,}},
{"3:2:2:3", 5, 4, 5, {GST_PRG, GST_ONE, GST_INT, GST_ONE, GST_PRG,}},
- {"2:3:3:2", 5, 4, 5, {GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,}},
+ /* fieldanalysis should indicate this using RFF on the second and fourth
+ * buffers and not send the third buffer at all. it will be identified as
+ * 3:2:2:3-RFF */
+ /* {"2:3:3:2", 5, 4, 5, {GST_PRG, GST_PRG, GST_DRP, GST_PRG, GST_PRG,}}, */
/* The following patterns are obscure and are ignored if ignore-obscure is
* set to true. If any patterns are added above this line, check and edit
GST_PRG, GST_PRG, GST_ONE, GST_INT, GST_INT,
GST_INT, GST_INT, GST_INT, GST_INT, GST_INT,
GST_INT, GST_INT, GST_INT, GST_ONE, GST_PRG,}},
+#if 0
/* 60i (NTSC 30000/1001) -> 16p (16000/1001) */
{"3:4-3", 15, 8, 15, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,
GST_DRP, GST_PRG, GST_DRP, GST_PRG, GST_DRP,
{"3:3:4", 5, 3, 5, {GST_PRG, GST_DRP, GST_PRG, GST_DRP, GST_PRG,}},
/* NTSC 60i -> 20p */
{"3:3", 3, 2, 3, {GST_PRG, GST_DRP, GST_PRG,}},
+#endif
/* NTSC 60i -> 27.5 */
{"3:2-4", 11, 10, 11, {GST_PRG, GST_PRG, GST_PRG, GST_PRG, GST_PRG,
GST_PRG, GST_ONE, GST_INT, GST_INT, GST_INT,
}
self->pattern_base_ts = self->buf_states[state_idx].timestamp;
- self->pattern_buf_dur =
- (self->buf_states[state_idx].duration *
- telecine_patterns[self->pattern].ratio_d) /
- telecine_patterns[self->pattern].ratio_n;
+ if (self->buf_states[state_idx].state != GST_RFF) {
+ self->pattern_buf_dur =
+ (self->buf_states[state_idx].duration *
+ telecine_patterns[self->pattern].ratio_d) /
+ telecine_patterns[self->pattern].ratio_n;
+ } else {
+ self->pattern_buf_dur =
+ (self->buf_states[state_idx].duration *
+ telecine_patterns[self->pattern].ratio_d * 2) /
+ (telecine_patterns[self->pattern].ratio_n * 3);
+ }
GST_DEBUG_OBJECT (self,
"Starting a new pattern repeat with base ts %" GST_TIME_FORMAT
" and dur %" GST_TIME_FORMAT, GST_TIME_ARGS (self->pattern_base_ts),
if (state) {
if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED) {
if (GST_VIDEO_FRAME_IS_RFF (frame)) {
- *state = GST_DEINTERLACE_BUFFER_STATE_DROP;
+ *state = GST_DEINTERLACE_BUFFER_STATE_RFF;
} else if (GST_VIDEO_FRAME_IS_ONEFIELD (frame)) {
/* tc top if tff, tc bottom otherwise */
if (GST_VIDEO_FRAME_IS_TFF (frame)) {
int i = 1;
GstClockTime timestamp;
GstDeinterlaceFieldLayout field_layout = self->field_layout;
- gboolean repeated;
gboolean tff;
gboolean onefield;
GstVideoFrame *frame = NULL;
/* we can manage the buffer ref count using the maps from here on */
gst_buffer_unref (buffer);
- repeated = GST_VIDEO_FRAME_IS_RFF (frame);
tff = GST_VIDEO_FRAME_IS_TFF (frame);
onefield = GST_VIDEO_FRAME_IS_ONEFIELD (frame);
- fields_to_push = (onefield) ? 1 : (!repeated) ? 2 : 3;
+ fields_to_push = (onefield) ? 1 : 2;
g_return_if_fail (self->history_count <
GST_DEINTERLACE_MAX_FIELD_HISTORY - fields_to_push);
if (self->state_count < GST_DEINTERLACE_MAX_BUFFER_STATE_HISTORY)
self->state_count++;
- if (buf_state == GST_DEINTERLACE_BUFFER_STATE_DROP) {
- GST_DEBUG_OBJECT (self,
- "Buffer contains only unneeded repeated fields, dropping and not"
- "adding to field history");
- gst_video_frame_unmap_and_free (frame);
- return;
- }
-
- /* telecine does not make use of repeated fields */
- if (interlacing_mode == GST_VIDEO_INTERLACE_MODE_MIXED && repeated) {
- repeated = FALSE;
- if (!onefield)
- fields_to_push = 2;
- }
-
for (i = GST_DEINTERLACE_MAX_FIELD_HISTORY - 1; i >= fields_to_push; i--) {
self->field_history[i].frame =
self->field_history[i - fields_to_push].frame;
field2_flags = PICTURE_INTERLACED_TOP;
}
- if (interlacing_mode != GST_VIDEO_INTERLACE_MODE_MIXED) {
+ if (interlacing_mode != GST_VIDEO_INTERLACE_MODE_MIXED || self->pattern <= 1) {
/* Timestamps are assigned to the field buffers under the assumption that
the timestamp of the buffer equals the first fields timestamp */
timestamp = GST_BUFFER_TIMESTAMP (buffer);
GST_BUFFER_TIMESTAMP (field1) = timestamp;
GST_BUFFER_TIMESTAMP (field2) = timestamp + self->field_duration;
- if (repeated)
- GST_BUFFER_TIMESTAMP (field2) += self->field_duration;
}
- if (repeated) {
- GST_DEBUG_OBJECT (self, "Repeated field");
- self->field_history[2].frame = field1;
- self->field_history[2].flags = field1_flags;
-
- self->field_history[1].frame = field2;
- self->field_history[1].flags = field2_flags;
-
- gst_video_frame_copy (self->field_history[0].frame, field1);
- GST_BUFFER_TIMESTAMP (self->field_history[0].frame->buffer) +=
- 2 * self->field_duration;
- self->field_history[0].flags = field1_flags;
- } else if (!onefield) {
+ if (!onefield) {
GST_DEBUG_OBJECT (self, "Two fields");
self->field_history[1].frame = field1;
self->field_history[1].flags = field1_flags;
do {
if (state & GST_ONE) {
field_count++;
+#if 0
} else if (!(state & GST_DRP)) {
+#endif
+ } else {
field_count += 2;
}
i++;
if (self->pattern == -1 || self->pattern_refresh
|| !(buf_state & pattern.states[(phase + count) % pattern.length])) {
+ if (self->pattern == -1) {
+ GST_DEBUG_OBJECT (self, "No pattern lock - refresh lock");
+ } else if (self->pattern_refresh) {
+ GST_DEBUG_OBJECT (self, "Pattern refresh - refresh lock");
+ } else {
+ GST_DEBUG_OBJECT (self, "Unexpected buffer state - refresh lock");
+ }
/* no pattern, pattern refresh set or unexpected buffer state */
self->pattern_lock = FALSE;
self->pattern_refresh = TRUE;