mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-20 00:31:13 +00:00
Set granulepos and timestamp correctly for streams not starting at 0, taking into account the initial delay
Original commit message from CVS: Set granulepos and timestamp correctly for streams not starting at 0, taking into account the initial delay
This commit is contained in:
parent
6f43a65dc6
commit
0df042ef00
4 changed files with 97 additions and 6 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
|||
2005-01-31 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* ext/theora/theoraenc.c: (theora_buffer_from_packet),
|
||||
(theora_enc_chain), (theora_enc_change_state):
|
||||
* ext/vorbis/vorbisenc.c: (gst_vorbisenc_init),
|
||||
(gst_vorbisenc_buffer_from_packet), (gst_vorbisenc_chain),
|
||||
(gst_vorbisenc_change_state):
|
||||
* ext/vorbis/vorbisenc.h:
|
||||
Set granulepos and timestamp correctly for streams not
|
||||
starting at 0, taking into account the initial delay.
|
||||
|
||||
2005-01-31 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* gst/mpegstream/gstdvddemux.c:
|
||||
|
|
|
@ -103,7 +103,7 @@ struct _GstTheoraEnc
|
|||
|
||||
guint packetno;
|
||||
guint64 bytes_out;
|
||||
guint64 next_ts;
|
||||
guint64 initial_delay;
|
||||
};
|
||||
|
||||
struct _GstTheoraEncClass
|
||||
|
@ -361,13 +361,24 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
|
|||
GstClockTime timestamp, GstClockTime duration)
|
||||
{
|
||||
GstBuffer *buf;
|
||||
guint64 granulepos_delta, timestamp_delta;
|
||||
|
||||
/* if duration is 0, it's a header packet and should
|
||||
* have granulepos 0 (so no delta regardless of delay) */
|
||||
if (duration == 0) {
|
||||
granulepos_delta = 0;
|
||||
timestamp_delta = 0;
|
||||
} else {
|
||||
granulepos_delta = enc->initial_delay * enc->fps / GST_SECOND;
|
||||
timestamp_delta = enc->initial_delay;
|
||||
}
|
||||
|
||||
buf = gst_pad_alloc_buffer (enc->srcpad,
|
||||
GST_BUFFER_OFFSET_NONE, packet->bytes);
|
||||
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
||||
GST_BUFFER_OFFSET (buf) = enc->bytes_out;
|
||||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
||||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos + granulepos_delta;
|
||||
GST_BUFFER_TIMESTAMP (buf) = timestamp + timestamp_delta;
|
||||
GST_BUFFER_DURATION (buf) = duration;
|
||||
|
||||
/* the second most significant bit of the first data byte is cleared
|
||||
|
@ -382,6 +393,11 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
|
|||
|
||||
enc->packetno++;
|
||||
|
||||
GST_DEBUG ("encoded buffer of %d bytes. granulepos = %" G_GINT64_FORMAT
|
||||
" + %" G_GINT64_FORMAT " = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buf),
|
||||
packet->granulepos, granulepos_delta,
|
||||
packet->granulepos + granulepos_delta);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
@ -450,6 +466,26 @@ theora_enc_chain (GstPad * pad, GstData * data)
|
|||
enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
|
||||
if (GST_IS_EVENT (data)) {
|
||||
switch (GST_EVENT_TYPE (data)) {
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
{
|
||||
guint64 val;
|
||||
|
||||
if (gst_event_discont_get_value (GST_EVENT (data), GST_FORMAT_TIME,
|
||||
&val)) {
|
||||
/* theora does not support discontinuities in the middle of
|
||||
* a stream so we can't just increase the granulepos to reflect
|
||||
* the new position, or can we? would that still be according
|
||||
* to spec? */
|
||||
if (enc->bytes_out == 0) {
|
||||
enc->initial_delay = val;
|
||||
GST_DEBUG ("initial delay = %" G_GUINT64_FORMAT, val);
|
||||
} else {
|
||||
GST_DEBUG ("mid stream discont: val = %" G_GUINT64_FORMAT, val);
|
||||
}
|
||||
}
|
||||
gst_pad_event_default (pad, GST_EVENT (data));
|
||||
return;
|
||||
}
|
||||
case GST_EVENT_EOS:
|
||||
/* push last packet with eos flag */
|
||||
while (theora_encode_packetout (&enc->state, 1, &op)) {
|
||||
|
@ -669,6 +705,7 @@ theora_enc_change_state (GstElement * element)
|
|||
theora_info_init (&enc->info);
|
||||
theora_comment_init (&enc->comment);
|
||||
enc->packetno = 0;
|
||||
enc->initial_delay = 0;
|
||||
break;
|
||||
case GST_STATE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
|
|
|
@ -483,6 +483,8 @@ gst_vorbisenc_init (VorbisEnc * vorbisenc)
|
|||
|
||||
vorbisenc->tags = gst_tag_list_new ();
|
||||
|
||||
vorbisenc->initial_delay = 0;
|
||||
|
||||
/* we're chained and we can deal with events */
|
||||
GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE);
|
||||
}
|
||||
|
@ -716,16 +718,32 @@ static GstBuffer *
|
|||
gst_vorbisenc_buffer_from_packet (VorbisEnc * vorbisenc, ogg_packet * packet)
|
||||
{
|
||||
GstBuffer *outbuf;
|
||||
guint64 granulepos_delta, timestamp_delta;
|
||||
|
||||
/* header packets always need to have granulepos 0,
|
||||
* regardless of the initial delay */
|
||||
if (packet->granulepos == 0) {
|
||||
granulepos_delta = 0;
|
||||
timestamp_delta = 0;
|
||||
} else {
|
||||
granulepos_delta =
|
||||
vorbisenc->initial_delay * vorbisenc->frequency / GST_SECOND;
|
||||
timestamp_delta = vorbisenc->initial_delay;
|
||||
}
|
||||
|
||||
outbuf = gst_buffer_new_and_alloc (packet->bytes);
|
||||
memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
|
||||
GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
|
||||
GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos;
|
||||
GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos + granulepos_delta;
|
||||
GST_BUFFER_TIMESTAMP (outbuf) =
|
||||
vorbis_granule_time_copy (&vorbisenc->vd,
|
||||
packet->granulepos) * GST_SECOND;
|
||||
packet->granulepos) * GST_SECOND + timestamp_delta;
|
||||
|
||||
GST_DEBUG ("encoded buffer of %d bytes. granulepos = %" G_GINT64_FORMAT
|
||||
" + %" G_GINT64_FORMAT " = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (outbuf),
|
||||
packet->granulepos, granulepos_delta,
|
||||
packet->granulepos + granulepos_delta);
|
||||
|
||||
GST_DEBUG ("encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
|
||||
return outbuf;
|
||||
}
|
||||
|
||||
|
@ -816,6 +834,24 @@ gst_vorbisenc_chain (GstPad * pad, GstData * _data)
|
|||
}
|
||||
gst_pad_event_default (pad, event);
|
||||
return;
|
||||
case GST_EVENT_DISCONTINUOUS:
|
||||
{
|
||||
guint64 val;
|
||||
|
||||
if (gst_event_discont_get_value (event, GST_FORMAT_TIME, &val)) {
|
||||
/* vorbis does not support discontinuities in the middle of
|
||||
* a stream so we can't just increase the granulepos to reflect
|
||||
* the new position, or can we? would that still be according
|
||||
* to spec? */
|
||||
if (vorbisenc->samples_in == 0) {
|
||||
vorbisenc->initial_delay = val;
|
||||
GST_DEBUG ("initial delay = %" G_GUINT64_FORMAT, val);
|
||||
} else {
|
||||
GST_DEBUG ("mid stream discont: val = %" G_GUINT64_FORMAT, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* fall through */
|
||||
default:
|
||||
gst_pad_event_default (pad, event);
|
||||
return;
|
||||
|
@ -1045,6 +1081,11 @@ gst_vorbisenc_change_state (GstElement * element)
|
|||
case GST_STATE_PAUSED_TO_READY:
|
||||
vorbisenc->setup = FALSE;
|
||||
vorbisenc->header_sent = FALSE;
|
||||
vorbisenc->initial_delay = 0;
|
||||
vorbisenc->samples_in = 0;
|
||||
vorbisenc->bytes_out = 0;
|
||||
vorbisenc->channels = -1;
|
||||
vorbisenc->frequency = -1;
|
||||
gst_tag_list_free (vorbisenc->tags);
|
||||
vorbisenc->tags = gst_tag_list_new ();
|
||||
break;
|
||||
|
|
|
@ -77,6 +77,8 @@ struct _VorbisEnc {
|
|||
gboolean setup;
|
||||
gboolean header_sent;
|
||||
gchar *last_message;
|
||||
|
||||
guint64 initial_delay; /* for streams not starting at timestamp/sample 0 */
|
||||
};
|
||||
|
||||
struct _VorbisEncClass {
|
||||
|
|
Loading…
Reference in a new issue