mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
ext/soundtouch/gstpitch.cc: Handle seeking correctly. Fixes #461068.
Original commit message from CVS: Patch by: Wouter Paesen <wouter at blue-gate dot be> * ext/soundtouch/gstpitch.cc: Handle seeking correctly. Fixes #461068.
This commit is contained in:
parent
610f0bde4c
commit
0830d14b27
2 changed files with 112 additions and 2 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
2007-11-15 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
|
Patch by: Wouter Paesen <wouter at blue-gate dot be>
|
||||||
|
|
||||||
|
* ext/soundtouch/gstpitch.cc:
|
||||||
|
Handle seeking correctly. Fixes #461068.
|
||||||
|
|
||||||
2007-11-15 Wim Taymans <wim.taymans@gmail.com>
|
2007-11-15 Wim Taymans <wim.taymans@gmail.com>
|
||||||
|
|
||||||
Patch by: Michael Kötter <m dot koetter at oraise dot de>
|
Patch by: Michael Kötter <m dot koetter at oraise dot de>
|
||||||
|
|
|
@ -44,6 +44,8 @@ struct _GstPitchPrivate
|
||||||
{
|
{
|
||||||
gfloat stream_time_ratio;
|
gfloat stream_time_ratio;
|
||||||
|
|
||||||
|
GstEvent *pending_segment;
|
||||||
|
|
||||||
soundtouch::SoundTouch * st;
|
soundtouch::SoundTouch * st;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,7 +110,7 @@ gst_pitch_base_init (gpointer g_class)
|
||||||
|
|
||||||
gst_element_class_set_details_simple (gstelement_class, "Pitch controller",
|
gst_element_class_set_details_simple (gstelement_class, "Pitch controller",
|
||||||
"Filter/Converter/Audio", "Control the pitch of an audio stream",
|
"Filter/Converter/Audio", "Control the pitch of an audio stream",
|
||||||
"Wouter Paesen <wouter@kangaroot.net>");
|
"Wouter Paesen <wouter@blue-gate.be>");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -448,6 +450,11 @@ gst_pitch_convert (GstPitch * pitch,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (src_format == *dst_format) {
|
||||||
|
*dst_value = src_value;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
switch (src_format) {
|
switch (src_format) {
|
||||||
case GST_FORMAT_BYTES:
|
case GST_FORMAT_BYTES:
|
||||||
switch (*dst_format) {
|
switch (*dst_format) {
|
||||||
|
@ -599,6 +606,67 @@ gst_pitch_src_query (GstPad * pad, GstQuery * query)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function returns FALSE if not enough data is known to transform the
|
||||||
|
* segment into proper downstream values. If the function does return false
|
||||||
|
* the sgement should be stalled until enough information is available.
|
||||||
|
* If the funtion returns TRUE, event will be replaced by the new downstream
|
||||||
|
* compatible event.
|
||||||
|
*/
|
||||||
|
static gboolean
|
||||||
|
gst_pitch_process_segment (GstPitch * pitch, GstEvent ** event)
|
||||||
|
{
|
||||||
|
GstFormat format, conv_format;
|
||||||
|
gint64 start_value, stop_value, base;
|
||||||
|
gint64 next_offset = 0, next_time = 0;
|
||||||
|
gboolean update = FALSE;
|
||||||
|
gdouble rate;
|
||||||
|
gfloat stream_time_ratio;
|
||||||
|
|
||||||
|
g_return_val_if_fail (event, FALSE);
|
||||||
|
|
||||||
|
GST_OBJECT_LOCK (pitch);
|
||||||
|
stream_time_ratio = pitch->priv->stream_time_ratio;
|
||||||
|
GST_OBJECT_UNLOCK (pitch);
|
||||||
|
|
||||||
|
gst_event_parse_new_segment (*event, &update, &rate, &format, &start_value,
|
||||||
|
&stop_value, &base);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (pitch->sinkpad, "segment %lld - %lld (%d)", start_value,
|
||||||
|
stop_value, format);
|
||||||
|
|
||||||
|
if (stream_time_ratio == 0) {
|
||||||
|
GST_LOG_OBJECT (pitch->sinkpad, "stream_time_ratio is zero");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_value = (gint64) (start_value / stream_time_ratio);
|
||||||
|
stop_value = (gint64) (stop_value / stream_time_ratio);
|
||||||
|
base = (gint64) (base / stream_time_ratio);
|
||||||
|
|
||||||
|
conv_format = GST_FORMAT_TIME;
|
||||||
|
if (!gst_pitch_convert (pitch, format, start_value, &conv_format, &next_time)) {
|
||||||
|
GST_LOG_OBJECT (pitch->sinkpad,
|
||||||
|
"could not convert segment start value to time");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
conv_format = GST_FORMAT_DEFAULT;
|
||||||
|
if (!gst_pitch_convert (pitch, format, start_value, &conv_format,
|
||||||
|
&next_offset)) {
|
||||||
|
GST_LOG_OBJECT (pitch->sinkpad,
|
||||||
|
"could not convert segment start value to offset");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
pitch->next_buffer_time = next_time;
|
||||||
|
pitch->next_buffer_offset = next_offset;
|
||||||
|
|
||||||
|
gst_event_unref (*event);
|
||||||
|
*event = gst_event_new_new_segment (update, rate, format, start_value,
|
||||||
|
stop_value, base);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_pitch_sink_event (GstPad * pad, GstEvent * event)
|
gst_pitch_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
@ -617,11 +685,21 @@ gst_pitch_sink_event (GstPad * pad, GstEvent * event)
|
||||||
case GST_EVENT_EOS:
|
case GST_EVENT_EOS:
|
||||||
gst_pitch_flush_buffer (pitch, TRUE);
|
gst_pitch_flush_buffer (pitch, TRUE);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_NEWSEGMENT:
|
||||||
|
if (!gst_pitch_process_segment (pitch, &event)) {
|
||||||
|
GST_LOG_OBJECT (pad, "not enough data known, stalling segment");
|
||||||
|
if (GST_PITCH_GET_PRIVATE (pitch)->pending_segment)
|
||||||
|
gst_event_unref (GST_PITCH_GET_PRIVATE (pitch)->pending_segment);
|
||||||
|
GST_PITCH_GET_PRIVATE (pitch)->pending_segment = event;
|
||||||
|
event = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* and forward it */
|
/* and forward it */
|
||||||
|
if (event)
|
||||||
res = gst_pad_event_default (pad, event);
|
res = gst_pad_event_default (pad, event);
|
||||||
|
|
||||||
gst_object_unref (pitch);
|
gst_object_unref (pitch);
|
||||||
|
@ -643,6 +721,25 @@ gst_pitch_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
GST_LOG_OBJECT (pitch, "incoming buffer (%d samples)",
|
GST_LOG_OBJECT (pitch, "incoming buffer (%d samples)",
|
||||||
(gint) (GST_BUFFER_SIZE (buffer) / pitch->sample_size));
|
(gint) (GST_BUFFER_SIZE (buffer) / pitch->sample_size));
|
||||||
|
|
||||||
|
if (GST_PITCH_GET_PRIVATE (pitch)->pending_segment) {
|
||||||
|
GstEvent *event =
|
||||||
|
gst_event_copy (GST_PITCH_GET_PRIVATE (pitch)->pending_segment);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (pitch, "processing stalled segment");
|
||||||
|
if (!gst_pitch_process_segment (pitch, &event)) {
|
||||||
|
gst_event_unref (event);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_pad_event_default (pitch->sinkpad, event)) {
|
||||||
|
gst_event_unref (event);
|
||||||
|
return GST_FLOW_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
gst_event_unref (GST_PITCH_GET_PRIVATE (pitch)->pending_segment);
|
||||||
|
GST_PITCH_GET_PRIVATE (pitch)->pending_segment = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
priv->st->putSamples ((gfloat *) GST_BUFFER_DATA (buffer),
|
priv->st->putSamples ((gfloat *) GST_BUFFER_DATA (buffer),
|
||||||
GST_BUFFER_SIZE (buffer) / pitch->sample_size);
|
GST_BUFFER_SIZE (buffer) / pitch->sample_size);
|
||||||
gst_buffer_unref (buffer);
|
gst_buffer_unref (buffer);
|
||||||
|
@ -683,7 +780,13 @@ gst_pitch_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
|
||||||
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
if (GST_PITCH_GET_PRIVATE (pitch)->pending_segment) {
|
||||||
|
gst_event_unref (GST_PITCH_GET_PRIVATE (pitch)->pending_segment);
|
||||||
|
GST_PITCH_GET_PRIVATE (pitch)->pending_segment = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue