mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 03:35:21 +00:00
ext/vorbis/vorbisenc.*: Keep track of the upstream segments and use the running time on that segment instead of the b...
Original commit message from CVS: Based on a patch by: Klaas <klaas at rivercrew dot net> * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_sink_event), (gst_vorbis_enc_buffer_check_discontinuous), (gst_vorbis_enc_chain), (gst_vorbis_enc_change_state): * ext/vorbis/vorbisenc.h: Keep track of the upstream segments and use the running time on that segment instead of the buffer timestamp everywhere. Fixes bug #525807.
This commit is contained in:
parent
c915582c17
commit
93f2eaa98c
3 changed files with 53 additions and 25 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2008-10-08 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
|
Based on a patch by: Klaas <klaas at rivercrew dot net>
|
||||||
|
|
||||||
|
* ext/vorbis/vorbisenc.c: (gst_vorbis_enc_sink_event),
|
||||||
|
(gst_vorbis_enc_buffer_check_discontinuous),
|
||||||
|
(gst_vorbis_enc_chain), (gst_vorbis_enc_change_state):
|
||||||
|
* ext/vorbis/vorbisenc.h:
|
||||||
|
Keep track of the upstream segments and use the running time on that
|
||||||
|
segment instead of the buffer timestamp everywhere. Fixes bug #525807.
|
||||||
|
|
||||||
2008-10-08 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
2008-10-08 Sebastian Dröge <sebastian.droege@collabora.co.uk>
|
||||||
|
|
||||||
* gst/audioconvert/audioconvert.c: (audio_convert_convert):
|
* gst/audioconvert/audioconvert.c: (audio_convert_convert):
|
||||||
|
|
|
@ -1033,6 +1033,20 @@ gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
|
||||||
}
|
}
|
||||||
res = gst_pad_push_event (vorbisenc->srcpad, event);
|
res = gst_pad_push_event (vorbisenc->srcpad, event);
|
||||||
break;
|
break;
|
||||||
|
case GST_EVENT_NEWSEGMENT:
|
||||||
|
{
|
||||||
|
gboolean update;
|
||||||
|
gdouble rate, applied_rate;
|
||||||
|
GstFormat format;
|
||||||
|
gint64 start, stop, position;
|
||||||
|
|
||||||
|
gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
|
||||||
|
&format, &start, &stop, &position);
|
||||||
|
if (format == GST_FORMAT_TIME)
|
||||||
|
gst_segment_set_newsegment (&vorbisenc->segment, update, rate, format,
|
||||||
|
start, stop, position);
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
default:
|
default:
|
||||||
res = gst_pad_push_event (vorbisenc->srcpad, event);
|
res = gst_pad_push_event (vorbisenc->srcpad, event);
|
||||||
break;
|
break;
|
||||||
|
@ -1042,33 +1056,29 @@ gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event)
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
|
gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc,
|
||||||
GstBuffer * buffer)
|
GstClockTime timestamp, GstClockTime duration)
|
||||||
{
|
{
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
|
||||||
if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
|
if (timestamp != GST_CLOCK_TIME_NONE &&
|
||||||
vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
||||||
GST_BUFFER_TIMESTAMP (buffer) != vorbisenc->expected_ts) {
|
duration != vorbisenc->expected_ts) {
|
||||||
/* It turns out that a lot of elements don't generate perfect streams due
|
/* It turns out that a lot of elements don't generate perfect streams due
|
||||||
* to rounding errors. So, we permit small errors (< 1/2 a sample) without
|
* to rounding errors. So, we permit small errors (< 1/2 a sample) without
|
||||||
* causing a discont.
|
* causing a discont.
|
||||||
*/
|
*/
|
||||||
int halfsample = GST_SECOND / vorbisenc->frequency / 2;
|
int halfsample = GST_SECOND / vorbisenc->frequency / 2;
|
||||||
|
|
||||||
if ((GstClockTimeDiff) (GST_BUFFER_TIMESTAMP (buffer) -
|
if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) {
|
||||||
vorbisenc->expected_ts) > halfsample) {
|
|
||||||
GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
|
GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT
|
||||||
", buffer TS %" GST_TIME_FORMAT,
|
", buffer TS %" GST_TIME_FORMAT,
|
||||||
GST_TIME_ARGS (vorbisenc->expected_ts),
|
GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp));
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE &&
|
if (timestamp != GST_CLOCK_TIME_NONE && duration != GST_CLOCK_TIME_NONE) {
|
||||||
GST_BUFFER_DURATION (buffer) != GST_CLOCK_TIME_NONE) {
|
vorbisenc->expected_ts = timestamp + duration;
|
||||||
vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer) +
|
|
||||||
GST_BUFFER_DURATION (buffer);
|
|
||||||
} else
|
} else
|
||||||
vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
|
vorbisenc->expected_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
@ -1086,12 +1096,17 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
float **vorbis_buffer;
|
float **vorbis_buffer;
|
||||||
GstBuffer *buf1, *buf2, *buf3;
|
GstBuffer *buf1, *buf2, *buf3;
|
||||||
gboolean first = FALSE;
|
gboolean first = FALSE;
|
||||||
|
GstClockTime timestamp = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
|
vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad));
|
||||||
|
|
||||||
if (!vorbisenc->setup)
|
if (!vorbisenc->setup)
|
||||||
goto not_setup;
|
goto not_setup;
|
||||||
|
|
||||||
|
timestamp =
|
||||||
|
gst_segment_to_running_time (&vorbisenc->segment, GST_FORMAT_TIME,
|
||||||
|
GST_BUFFER_TIMESTAMP (buffer));
|
||||||
|
|
||||||
if (!vorbisenc->header_sent) {
|
if (!vorbisenc->header_sent) {
|
||||||
/* Vorbis streams begin with three headers; the initial header (with
|
/* Vorbis streams begin with three headers; the initial header (with
|
||||||
most of the codec setup parameters) which is mandated by the Ogg
|
most of the codec setup parameters) which is mandated by the Ogg
|
||||||
|
@ -1148,10 +1163,10 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
|
|
||||||
/* now adjust starting granulepos accordingly if the buffer's timestamp is
|
/* now adjust starting granulepos accordingly if the buffer's timestamp is
|
||||||
nonzero */
|
nonzero */
|
||||||
vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
|
vorbisenc->next_ts = timestamp;
|
||||||
vorbisenc->expected_ts = GST_BUFFER_TIMESTAMP (buffer);
|
vorbisenc->expected_ts = timestamp;
|
||||||
vorbisenc->granulepos_offset = gst_util_uint64_scale
|
vorbisenc->granulepos_offset = gst_util_uint64_scale
|
||||||
(GST_BUFFER_TIMESTAMP (buffer), vorbisenc->frequency, GST_SECOND);
|
(timestamp, vorbisenc->frequency, GST_SECOND);
|
||||||
vorbisenc->subgranule_offset = 0;
|
vorbisenc->subgranule_offset = 0;
|
||||||
vorbisenc->subgranule_offset =
|
vorbisenc->subgranule_offset =
|
||||||
vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
|
vorbisenc->next_ts - granulepos_to_timestamp_offset (vorbisenc, 0);
|
||||||
|
@ -1161,15 +1176,14 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE &&
|
||||||
GST_BUFFER_TIMESTAMP (buffer) < vorbisenc->expected_ts) {
|
timestamp < vorbisenc->expected_ts) {
|
||||||
guint64 diff = vorbisenc->expected_ts - GST_BUFFER_TIMESTAMP (buffer);
|
guint64 diff = vorbisenc->expected_ts - timestamp;
|
||||||
guint64 diff_bytes;
|
guint64 diff_bytes;
|
||||||
|
|
||||||
GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
|
GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous "
|
||||||
"timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
|
"timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT
|
||||||
"), cannot handle. Clipping buffer.",
|
"), cannot handle. Clipping buffer.",
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
|
GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts));
|
||||||
GST_TIME_ARGS (vorbisenc->expected_ts));
|
|
||||||
|
|
||||||
diff_bytes =
|
diff_bytes =
|
||||||
GST_CLOCK_TIME_TO_FRAMES (diff,
|
GST_CLOCK_TIME_TO_FRAMES (diff,
|
||||||
|
@ -1187,11 +1201,12 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
GST_BUFFER_DURATION (buffer) -= diff;
|
GST_BUFFER_DURATION (buffer) -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, buffer) && !first) {
|
if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp,
|
||||||
GST_WARNING_OBJECT (vorbisenc, "Buffer is discontinuous, flushing encoder "
|
GST_BUFFER_DURATION (buffer)) && !first) {
|
||||||
"and restarting (Discont from %" GST_TIME_FORMAT
|
GST_WARNING_OBJECT (vorbisenc,
|
||||||
" to %" GST_TIME_FORMAT ")", GST_TIME_ARGS (vorbisenc->next_ts),
|
"Buffer is discontinuous, flushing encoder "
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
|
"and restarting (Discont from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT
|
||||||
|
")", GST_TIME_ARGS (vorbisenc->next_ts), GST_TIME_ARGS (timestamp));
|
||||||
/* Re-initialise encoder (there's unfortunately no API to flush it) */
|
/* Re-initialise encoder (there's unfortunately no API to flush it) */
|
||||||
if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
|
if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK)
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1200,11 +1215,11 @@ gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
we successfully initialised earlier */
|
we successfully initialised earlier */
|
||||||
|
|
||||||
/* Now, set our granulepos offset appropriately. */
|
/* Now, set our granulepos offset appropriately. */
|
||||||
vorbisenc->next_ts = GST_BUFFER_TIMESTAMP (buffer);
|
vorbisenc->next_ts = timestamp;
|
||||||
/* We need to round to the nearest whole number of samples, not just do
|
/* We need to round to the nearest whole number of samples, not just do
|
||||||
* a truncating division here */
|
* a truncating division here */
|
||||||
vorbisenc->granulepos_offset = gst_util_uint64_scale
|
vorbisenc->granulepos_offset = gst_util_uint64_scale
|
||||||
(GST_BUFFER_TIMESTAMP (buffer) + GST_SECOND / vorbisenc->frequency / 2
|
(timestamp + GST_SECOND / vorbisenc->frequency / 2
|
||||||
- vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
|
- vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND);
|
||||||
|
|
||||||
vorbisenc->header_sent = TRUE;
|
vorbisenc->header_sent = TRUE;
|
||||||
|
@ -1418,6 +1433,7 @@ gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition)
|
||||||
vorbisenc->setup = FALSE;
|
vorbisenc->setup = FALSE;
|
||||||
vorbisenc->next_discont = FALSE;
|
vorbisenc->next_discont = FALSE;
|
||||||
vorbisenc->header_sent = FALSE;
|
vorbisenc->header_sent = FALSE;
|
||||||
|
gst_segment_init (&vorbisenc->segment, GST_FORMAT_TIME);
|
||||||
break;
|
break;
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -80,6 +80,7 @@ struct _GstVorbisEnc {
|
||||||
gboolean next_discont;
|
gboolean next_discont;
|
||||||
guint64 granulepos_offset;
|
guint64 granulepos_offset;
|
||||||
gint64 subgranule_offset;
|
gint64 subgranule_offset;
|
||||||
|
GstSegment segment;
|
||||||
|
|
||||||
GstTagList * tags;
|
GstTagList * tags;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue