mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
deinterlace: Timecode pass-through
When it is trivial to pass-through a timecode, by only removing the "interlaced" flag, do pass-through. Otherwise, double the fps_n and adjust the "frames" field. https://bugzilla.gnome.org/show_bug.cgi?id=796818
This commit is contained in:
parent
f672116c72
commit
ceac1b51b1
3 changed files with 84 additions and 8 deletions
|
@ -735,6 +735,7 @@ gst_deinterlace_init (GstDeinterlace * self)
|
|||
self->pattern_base_ts = GST_CLOCK_TIME_NONE;
|
||||
self->pattern_buf_dur = GST_CLOCK_TIME_NONE;
|
||||
self->still_frame_mode = FALSE;
|
||||
self->telecine_tc_warned = FALSE;
|
||||
|
||||
gst_deinterlace_reset (self);
|
||||
}
|
||||
|
@ -782,6 +783,9 @@ gst_deinterlace_reset_history (GstDeinterlace * self, gboolean drop_all)
|
|||
if (self->field_history[i].frame) {
|
||||
gst_video_frame_unmap_and_free (self->field_history[i].frame);
|
||||
self->field_history[i].frame = NULL;
|
||||
if (self->field_history[i].tc) {
|
||||
gst_video_time_code_free (self->field_history[i].tc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -833,6 +837,7 @@ gst_deinterlace_reset (GstDeinterlace * self)
|
|||
self->have_eos = FALSE;
|
||||
|
||||
self->discont = TRUE;
|
||||
self->telecine_tc_warned = FALSE;
|
||||
|
||||
gst_deinterlace_set_allocation (self, NULL, NULL, NULL);
|
||||
}
|
||||
|
@ -1089,8 +1094,6 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
|
|||
* if this is not the case, change the map flags as appropriate
|
||||
*/
|
||||
frame = gst_video_frame_new_and_map (&self->vinfo, buffer, GST_MAP_READ);
|
||||
/* we can manage the buffer ref count using the maps from here on */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
tff = GST_VIDEO_FRAME_IS_TFF (frame);
|
||||
onefield = GST_VIDEO_FRAME_IS_ONEFIELD (frame);
|
||||
|
@ -1126,6 +1129,14 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
|
|||
self->field_history[i - fields_to_push].frame;
|
||||
self->field_history[i].flags =
|
||||
self->field_history[i - fields_to_push].flags;
|
||||
if (self->field_history[i].tc)
|
||||
gst_video_time_code_free (self->field_history[i].tc);
|
||||
if (self->field_history[i - fields_to_push].tc) {
|
||||
self->field_history[i].tc =
|
||||
gst_video_time_code_copy (self->field_history[i - fields_to_push].tc);
|
||||
} else {
|
||||
self->field_history[i].tc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (field_layout == GST_DEINTERLACE_LAYOUT_AUTO) {
|
||||
|
@ -1159,19 +1170,40 @@ gst_deinterlace_push_history (GstDeinterlace * self, GstBuffer * buffer)
|
|||
}
|
||||
|
||||
if (!onefield) {
|
||||
GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Two fields");
|
||||
self->field_history[1].frame = field1;
|
||||
self->field_history[1].flags = field1_flags;
|
||||
|
||||
self->field_history[0].frame = field2;
|
||||
self->field_history[0].flags = field2_flags;
|
||||
|
||||
if (meta) {
|
||||
self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
|
||||
self->field_history[0].tc->config.flags &=
|
||||
~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
|
||||
self->field_history[1].tc = gst_video_time_code_copy (&meta->tc);
|
||||
self->field_history[1].tc->config.flags &=
|
||||
~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
|
||||
}
|
||||
} else { /* onefield */
|
||||
GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (buffer);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "One field");
|
||||
self->field_history[0].frame = field1;
|
||||
self->field_history[0].flags = field1_flags;
|
||||
if (meta) {
|
||||
self->field_history[0].tc = gst_video_time_code_copy (&meta->tc);
|
||||
self->field_history[0].tc->config.flags &=
|
||||
~GST_VIDEO_TIME_CODE_FLAGS_INTERLACED;
|
||||
}
|
||||
gst_video_frame_unmap_and_free (field2);
|
||||
}
|
||||
|
||||
/* we can manage the buffer ref count using the maps from here on */
|
||||
gst_buffer_unref (buffer);
|
||||
|
||||
self->history_count += fields_to_push;
|
||||
self->cur_field_idx += fields_to_push;
|
||||
|
||||
|
@ -1733,6 +1765,8 @@ restart:
|
|||
|| IS_TELECINE (interlacing_mode)))
|
||||
|| (self->fields == GST_DEINTERLACE_ALL
|
||||
&& !IS_TELECINE (interlacing_mode))) {
|
||||
gint index;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "deinterlacing top field");
|
||||
|
||||
/* create new buffer */
|
||||
|
@ -1743,10 +1777,28 @@ restart:
|
|||
g_return_val_if_fail (self->history_count >=
|
||||
1 + gst_deinterlace_method_get_latency (self->method), GST_FLOW_ERROR);
|
||||
|
||||
buf =
|
||||
self->field_history[self->history_count - 1 -
|
||||
gst_deinterlace_method_get_latency (self->method)].frame->buffer;
|
||||
index =
|
||||
self->history_count - 1 -
|
||||
gst_deinterlace_method_get_latency (self->method);
|
||||
buf = self->field_history[index].frame->buffer;
|
||||
|
||||
if (self->field_history[index].tc) {
|
||||
gst_buffer_add_video_time_code_meta (outbuf,
|
||||
self->field_history[index].tc);
|
||||
}
|
||||
if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
|
||||
self->telecine_tc_warned = TRUE;
|
||||
GST_FIXME_OBJECT (self,
|
||||
"Detected telecine timecodes when deinterlacing. This is not "
|
||||
"supported yet. Resulting timecode may be wrong");
|
||||
}
|
||||
if (self->fields == GST_DEINTERLACE_ALL) {
|
||||
GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
|
||||
if (meta) {
|
||||
meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
|
||||
meta->tc.frames = 2 * meta->tc.frames;
|
||||
}
|
||||
}
|
||||
if (!IS_TELECINE (interlacing_mode)) {
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||
|
||||
|
@ -1880,6 +1932,8 @@ restart:
|
|||
|| IS_TELECINE (interlacing_mode)))
|
||||
|| (self->fields == GST_DEINTERLACE_ALL
|
||||
&& !IS_TELECINE (interlacing_mode))) {
|
||||
gint index;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "deinterlacing bottom field");
|
||||
|
||||
/* create new buffer */
|
||||
|
@ -1890,9 +1944,28 @@ restart:
|
|||
g_return_val_if_fail (self->history_count >=
|
||||
gst_deinterlace_method_get_latency (self->method) + 1, GST_FLOW_ERROR);
|
||||
|
||||
buf =
|
||||
self->field_history[self->history_count - 1 -
|
||||
gst_deinterlace_method_get_latency (self->method)].frame->buffer;
|
||||
index =
|
||||
self->history_count - 1 -
|
||||
gst_deinterlace_method_get_latency (self->method);
|
||||
buf = self->field_history[index].frame->buffer;
|
||||
|
||||
if (self->field_history[index].tc) {
|
||||
gst_buffer_add_video_time_code_meta (outbuf,
|
||||
self->field_history[index].tc);
|
||||
}
|
||||
if (IS_TELECINE (interlacing_mode) && !self->telecine_tc_warned) {
|
||||
self->telecine_tc_warned = TRUE;
|
||||
GST_FIXME_OBJECT (self,
|
||||
"Detected telecine timecodes when deinterlacing. This is not "
|
||||
"supported yet. Resulting timecode may be wrong");
|
||||
}
|
||||
if (self->fields == GST_DEINTERLACE_ALL) {
|
||||
GstVideoTimeCodeMeta *meta = gst_buffer_get_video_time_code_meta (outbuf);
|
||||
if (meta) {
|
||||
meta->tc.config.fps_n = 2 * meta->tc.config.fps_n;
|
||||
meta->tc.frames = 2 * meta->tc.frames + 1;
|
||||
}
|
||||
}
|
||||
if (!IS_TELECINE (interlacing_mode)) {
|
||||
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||
|
||||
|
@ -2900,6 +2973,7 @@ gst_deinterlace_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
|
|||
GST_DEBUG_OBJECT (self, "Ending still frames");
|
||||
self->still_frame_mode = FALSE;
|
||||
}
|
||||
self->telecine_tc_warned = FALSE;
|
||||
gst_deinterlace_reset_qos (self);
|
||||
res = gst_pad_push_event (self->srcpad, event);
|
||||
gst_deinterlace_reset_history (self, TRUE);
|
||||
|
|
|
@ -194,6 +194,7 @@ struct _GstDeinterlace
|
|||
|
||||
gboolean need_more;
|
||||
gboolean have_eos;
|
||||
gboolean telecine_tc_warned;
|
||||
};
|
||||
|
||||
struct _GstDeinterlaceClass
|
||||
|
|
|
@ -54,6 +54,7 @@ typedef struct
|
|||
GstVideoFrame *frame;
|
||||
/* see PICTURE_ flags in *.c */
|
||||
guint flags;
|
||||
GstVideoTimeCode *tc;
|
||||
} GstDeinterlaceField;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue