mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-05 06:58:49 +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>
|
2005-01-31 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
* gst/mpegstream/gstdvddemux.c:
|
* gst/mpegstream/gstdvddemux.c:
|
||||||
|
|
|
@ -103,7 +103,7 @@ struct _GstTheoraEnc
|
||||||
|
|
||||||
guint packetno;
|
guint packetno;
|
||||||
guint64 bytes_out;
|
guint64 bytes_out;
|
||||||
guint64 next_ts;
|
guint64 initial_delay;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstTheoraEncClass
|
struct _GstTheoraEncClass
|
||||||
|
@ -361,13 +361,24 @@ theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet,
|
||||||
GstClockTime timestamp, GstClockTime duration)
|
GstClockTime timestamp, GstClockTime duration)
|
||||||
{
|
{
|
||||||
GstBuffer *buf;
|
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,
|
buf = gst_pad_alloc_buffer (enc->srcpad,
|
||||||
GST_BUFFER_OFFSET_NONE, packet->bytes);
|
GST_BUFFER_OFFSET_NONE, packet->bytes);
|
||||||
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes);
|
||||||
GST_BUFFER_OFFSET (buf) = enc->bytes_out;
|
GST_BUFFER_OFFSET (buf) = enc->bytes_out;
|
||||||
GST_BUFFER_OFFSET_END (buf) = packet->granulepos;
|
GST_BUFFER_OFFSET_END (buf) = packet->granulepos + granulepos_delta;
|
||||||
GST_BUFFER_TIMESTAMP (buf) = timestamp;
|
GST_BUFFER_TIMESTAMP (buf) = timestamp + timestamp_delta;
|
||||||
GST_BUFFER_DURATION (buf) = duration;
|
GST_BUFFER_DURATION (buf) = duration;
|
||||||
|
|
||||||
/* the second most significant bit of the first data byte is cleared
|
/* 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++;
|
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;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,6 +466,26 @@ theora_enc_chain (GstPad * pad, GstData * data)
|
||||||
enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
|
enc = GST_THEORA_ENC (gst_pad_get_parent (pad));
|
||||||
if (GST_IS_EVENT (data)) {
|
if (GST_IS_EVENT (data)) {
|
||||||
switch (GST_EVENT_TYPE (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:
|
case GST_EVENT_EOS:
|
||||||
/* push last packet with eos flag */
|
/* push last packet with eos flag */
|
||||||
while (theora_encode_packetout (&enc->state, 1, &op)) {
|
while (theora_encode_packetout (&enc->state, 1, &op)) {
|
||||||
|
@ -669,6 +705,7 @@ theora_enc_change_state (GstElement * element)
|
||||||
theora_info_init (&enc->info);
|
theora_info_init (&enc->info);
|
||||||
theora_comment_init (&enc->comment);
|
theora_comment_init (&enc->comment);
|
||||||
enc->packetno = 0;
|
enc->packetno = 0;
|
||||||
|
enc->initial_delay = 0;
|
||||||
break;
|
break;
|
||||||
case GST_STATE_PAUSED_TO_PLAYING:
|
case GST_STATE_PAUSED_TO_PLAYING:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -483,6 +483,8 @@ gst_vorbisenc_init (VorbisEnc * vorbisenc)
|
||||||
|
|
||||||
vorbisenc->tags = gst_tag_list_new ();
|
vorbisenc->tags = gst_tag_list_new ();
|
||||||
|
|
||||||
|
vorbisenc->initial_delay = 0;
|
||||||
|
|
||||||
/* we're chained and we can deal with events */
|
/* we're chained and we can deal with events */
|
||||||
GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE);
|
GST_FLAG_SET (vorbisenc, GST_ELEMENT_EVENT_AWARE);
|
||||||
}
|
}
|
||||||
|
@ -716,16 +718,32 @@ static GstBuffer *
|
||||||
gst_vorbisenc_buffer_from_packet (VorbisEnc * vorbisenc, ogg_packet * packet)
|
gst_vorbisenc_buffer_from_packet (VorbisEnc * vorbisenc, ogg_packet * packet)
|
||||||
{
|
{
|
||||||
GstBuffer *outbuf;
|
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);
|
outbuf = gst_buffer_new_and_alloc (packet->bytes);
|
||||||
memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
|
memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes);
|
||||||
GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out;
|
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) =
|
GST_BUFFER_TIMESTAMP (outbuf) =
|
||||||
vorbis_granule_time_copy (&vorbisenc->vd,
|
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;
|
return outbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -816,6 +834,24 @@ gst_vorbisenc_chain (GstPad * pad, GstData * _data)
|
||||||
}
|
}
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
return;
|
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:
|
default:
|
||||||
gst_pad_event_default (pad, event);
|
gst_pad_event_default (pad, event);
|
||||||
return;
|
return;
|
||||||
|
@ -1045,6 +1081,11 @@ gst_vorbisenc_change_state (GstElement * element)
|
||||||
case GST_STATE_PAUSED_TO_READY:
|
case GST_STATE_PAUSED_TO_READY:
|
||||||
vorbisenc->setup = FALSE;
|
vorbisenc->setup = FALSE;
|
||||||
vorbisenc->header_sent = 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);
|
gst_tag_list_free (vorbisenc->tags);
|
||||||
vorbisenc->tags = gst_tag_list_new ();
|
vorbisenc->tags = gst_tag_list_new ();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -77,6 +77,8 @@ struct _VorbisEnc {
|
||||||
gboolean setup;
|
gboolean setup;
|
||||||
gboolean header_sent;
|
gboolean header_sent;
|
||||||
gchar *last_message;
|
gchar *last_message;
|
||||||
|
|
||||||
|
guint64 initial_delay; /* for streams not starting at timestamp/sample 0 */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _VorbisEncClass {
|
struct _VorbisEncClass {
|
||||||
|
|
Loading…
Reference in a new issue