From 45b9c254157e3cf558680a804f80ea2f293c7245 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sat, 5 Jun 2004 18:50:48 +0000 Subject: [PATCH] gst/qtdemux/qtdemux.*: Bitch. Also known as seeking, querying & co. Original commit message from CVS: * gst/qtdemux/qtdemux.c: (gst_qtdemux_init), (gst_qtdemux_handle_src_query), (gst_qtdemux_handle_src_event), (gst_qtdemux_handle_sink_event), (gst_qtdemux_change_state), (gst_qtdemux_loop_header), (qtdemux_dump_mvhd), (qtdemux_parse_trak): * gst/qtdemux/qtdemux.h: Bitch. Also known as seeking, querying & co. * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_chain), (gst_osssink_change_state): * sys/oss/gstosssink.h: Resyncing is for weenies, this hack is no longer needed and was broken anyway (since it - unintendedly - always leaves resync to TRUE). --- ChangeLog | 16 +++++++++ gst/qtdemux/qtdemux.c | 99 ++++++++++++++++++++++++++++++++++++++++----------- gst/qtdemux/qtdemux.h | 3 ++ sys/oss/gstosssink.c | 44 +++++++++-------------- sys/oss/gstosssink.h | 1 - 5 files changed, 114 insertions(+), 49 deletions(-) diff --git a/ChangeLog b/ChangeLog index 175034c..7b60b12 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2004-06-04 Ronald Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_init), + (gst_qtdemux_handle_src_query), (gst_qtdemux_handle_src_event), + (gst_qtdemux_handle_sink_event), (gst_qtdemux_change_state), + (gst_qtdemux_loop_header), (qtdemux_dump_mvhd), + (qtdemux_parse_trak): + * gst/qtdemux/qtdemux.h: + Bitch. Also known as seeking, querying & co. + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_chain), + (gst_osssink_change_state): + * sys/oss/gstosssink.h: + Resyncing is for weenies, this hack is no longer needed and was + broken anyway (since it - unintendedly - always leaves resync to + TRUE). + 2004-06-05 Andrew Turner * gst/tcp/gsttcp.c: portability (Solaris 10/FreeBSD) diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index 833c805..6b97ad2 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -231,6 +231,10 @@ gst_qtdemux_init (GstQTDemux * qtdemux) gst_element_set_loop_function (GST_ELEMENT (qtdemux), gst_qtdemux_loop_header); gst_element_add_pad (GST_ELEMENT (qtdemux), qtdemux->sinkpad); + + qtdemux->last_ts = GST_CLOCK_TIME_NONE; + qtdemux->need_discont = FALSE; + qtdemux->need_flush = FALSE; } static const GstFormat * @@ -332,7 +336,8 @@ static gboolean gst_qtdemux_handle_src_query (GstPad * pad, GstQueryType type, GstFormat * format, gint64 * value) { - gboolean res = TRUE; + gboolean res = FALSE; + GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad)); //QtDemuxStream *stream = gst_pad_get_element_private(pad); @@ -340,7 +345,11 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQueryType type, case GST_QUERY_TOTAL: switch (*format) { case GST_FORMAT_TIME: - *value = 0; /* FIXME */ + if (qtdemux->duration != 0 && qtdemux->timescale != 0) { + *value = + (guint64) qtdemux->duration * GST_SECOND / qtdemux->timescale; + res = TRUE; + } break; case GST_FORMAT_BYTES: *value = 0; /* FIXME */ @@ -356,7 +365,10 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQueryType type, case GST_QUERY_POSITION: switch (*format) { case GST_FORMAT_TIME: - *value = 0; /* FIXME */ + if (GST_CLOCK_TIME_IS_VALID (qtdemux->last_ts)) { + *value = qtdemux->last_ts; + res = TRUE; + } break; case GST_FORMAT_BYTES: *value = 0; /* FIXME */ @@ -381,8 +393,7 @@ static gboolean gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event) { gboolean res = TRUE; - - //QtDemuxStream *stream = gst_pad_get_element_private(pad); + GstQTDemux *qtdemux = GST_QTDEMUX (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: @@ -391,13 +402,35 @@ gst_qtdemux_handle_src_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_SEEK_FORMAT (event)) { case GST_FORMAT_BYTES: case GST_FORMAT_DEFAULT: + res = FALSE; + break; case GST_FORMAT_TIME: { gint64 desired_offset = GST_EVENT_SEEK_OFFSET (event); + gint i = 0, n; + QtDemuxStream *stream = gst_pad_get_element_private (pad); GST_DEBUG ("seeking to %" G_GINT64_FORMAT, desired_offset); - res = FALSE; + if (!stream->n_samples) { + res = FALSE; + break; + } + + /* resync to new time */ + for (n = 0; n < qtdemux->n_streams; n++) { + QtDemuxStream *str = qtdemux->streams[n]; + + for (i = 0; i < str->n_samples; i++) { + if (str->samples[i].timestamp > desired_offset) + break; + } + str->sample_index = i; + } + qtdemux->need_discont = TRUE; + if (GST_EVENT_SEEK_FLAGS (event) & GST_SEEK_FLAG_FLUSH) + qtdemux->need_flush = TRUE; + break; } default: res = FALSE; @@ -456,7 +489,6 @@ gst_qtdemux_handle_sink_event (GstQTDemux * qtdemux) gst_pad_event_default (qtdemux->sinkpad, event); return FALSE; case GST_EVENT_FLUSH: - //g_warning("flush event"); break; case GST_EVENT_DISCONTINUOUS: GST_DEBUG ("discontinuous event"); @@ -490,6 +522,9 @@ gst_qtdemux_change_state (GstElement * element) case GST_STATE_PLAYING_TO_PAUSED: break; case GST_STATE_PAUSED_TO_READY: + qtdemux->last_ts = GST_CLOCK_TIME_NONE; + qtdemux->need_discont = FALSE; + qtdemux->need_flush = FALSE; break; case GST_STATE_READY_TO_NULL: gst_bytestream_destroy (qtdemux->bs); @@ -727,8 +762,29 @@ gst_qtdemux_loop_header (GstElement * element) GST_BUFFER_TIMESTAMP (buf) = stream->samples[stream->sample_index].timestamp; + qtdemux->last_ts = GST_BUFFER_TIMESTAMP (buf); GST_BUFFER_DURATION (buf) = stream->samples[stream->sample_index].duration; + if (qtdemux->need_flush) { + gst_pad_event_default (qtdemux->sinkpad, + gst_event_new (GST_EVENT_FLUSH)); + qtdemux->need_flush = FALSE; + } + if (qtdemux->need_discont) { + GstEvent *event = gst_event_new_discontinuous (FALSE, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf), + GST_FORMAT_UNDEFINED); + gint n; + + qtdemux->need_discont = FALSE; + for (n = 0; n < qtdemux->n_streams; n++) { + gst_event_ref (event); + gst_pad_push (qtdemux->streams[n]->pad, GST_DATA (event)); + } + gst_event_unref (event); + } + g_print ("Pushing buf with time=%" GST_TIME_FORMAT "\n", + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); gst_pad_push (stream->pad, GST_DATA (buf)); GST_INFO ("pushing buffer on %" GST_PTR_FORMAT, stream->pad); @@ -1307,6 +1363,8 @@ qtdemux_dump_mvhd (GstQTDemux * qtdemux, void *buffer, int depth) QTDEMUX_GUINT32_GET (buffer + 20)); GST_LOG ("%*s duration: %u", depth, "", QTDEMUX_GUINT32_GET (buffer + 24)); + qtdemux->duration = QTDEMUX_GUINT32_GET (buffer + 24); + qtdemux->timescale = QTDEMUX_GUINT32_GET (buffer + 20); GST_LOG ("%*s pref. rate: %g", depth, "", QTDEMUX_FP32_GET (buffer + 28)); GST_LOG ("%*s pref. volume: %g", depth, "", QTDEMUX_FP16_GET (buffer + 32)); GST_LOG ("%*s preview time: %u", depth, "", @@ -2077,30 +2135,31 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) sample_index += samples_per_chunk; } } -/* -done2: - n_sample_times = QTDEMUX_GUINT32_GET(stts->data + 12); - GST_LOG("n_sample_times = %d",n_sample_times); +#if 0 + done2: + n_sample_times = QTDEMUX_GUINT32_GET (stts->data + 12); + GST_LOG ("n_sample_times = %d", n_sample_times); timestamp = 0; index = 0; sample_index = 0; - for(i=0;idata + 16 + 8*i); - duration = QTDEMUX_GUINT32_GET(stts->data + 16 + 8*i + 4); - for(;index < n_samples && samples[index].sample_index < sample_index;index++){ - int size; + + sample_index += QTDEMUX_GUINT32_GET (stts->data + 16 + 8 * i); + duration = QTDEMUX_GUINT32_GET (stts->data + 16 + 8 * i + 4); + for (; index < n_samples && samples[index].sample_index < sample_index; + index++) { + int size; samples[index].timestamp = timestamp; - size = samples[index+1].sample_index - samples[index].sample_index; - time = GST_SECOND / stream->rate; //(GST_SECOND * duration * samples[index].size)/stream->timescale ; + size = samples[index + 1].sample_index - samples[index].sample_index; + time = GST_SECOND / stream->rate; //(GST_SECOND * duration * samples[index].size)/stream->timescale ; timestamp += time; samples[index].duration = time; } } -*/ +#endif } done2: #if 0 diff --git a/gst/qtdemux/qtdemux.h b/gst/qtdemux/qtdemux.h index 0feaea0..d6ed313 100644 --- a/gst/qtdemux/qtdemux.h +++ b/gst/qtdemux/qtdemux.h @@ -74,6 +74,9 @@ struct _GstQTDemux { /* track stuff */ + guint64 last_ts; + gboolean need_discont; + gboolean need_flush; }; struct _GstQTDemuxClass { diff --git a/sys/oss/gstosssink.c b/sys/oss/gstosssink.c index 08de079..befb57f 100644 --- a/sys/oss/gstosssink.c +++ b/sys/oss/gstosssink.c @@ -218,7 +218,6 @@ gst_osssink_init (GstOssSink * osssink) osssink->chunk_size = 4096; osssink->mute = FALSE; osssink->sync = TRUE; - osssink->resync = TRUE; osssink->provided_clock = gst_audio_clock_new ("ossclock", gst_osssink_get_time, osssink); gst_object_set_parent (GST_OBJECT (osssink->provided_clock), @@ -392,9 +391,6 @@ gst_osssink_chain (GstPad * pad, GstData * _data) FALSE); gst_pad_event_default (pad, event); return; - case GST_EVENT_DISCONTINUOUS: - osssink->resync = TRUE; - /* pass-through */ default: gst_pad_event_default (pad, event); return; @@ -424,13 +420,13 @@ gst_osssink_chain (GstPad * pad, GstData * _data) buftime = soundtime; } GST_LOG_OBJECT (osssink, - "time: real %" G_GUINT64_FORMAT ", buffer: %" G_GUINT64_FORMAT, soundtime, - buftime); + "time: real %" GST_TIME_FORMAT ", buffer: %" GST_TIME_FORMAT, + GST_TIME_ARGS (soundtime), GST_TIME_ARGS (buftime)); if (MAX (buftime, soundtime) - MIN (buftime, soundtime) > (GST_SECOND / 10)) { /* we need to adjust to the buffers here */ GST_INFO_OBJECT (osssink, - "need sync: real %" G_GUINT64_FORMAT ", buffer: %" G_GUINT64_FORMAT, - soundtime, buftime); + "need sync: real %" GST_TIME_FORMAT ", buffer: %" GST_TIME_FORMAT, + GST_TIME_ARGS (soundtime), GST_TIME_ARGS (buftime)); if (soundtime > buftime) { /* do *not* throw frames out. It's useless. The next frame will come in * too late. And the next one. And so on. We don't want to lose sound. @@ -444,29 +440,22 @@ gst_osssink_chain (GstPad * pad, GstData * _data) GST_OSSELEMENT (osssink)->channels)) * (GST_OSSELEMENT (osssink)->width / 8) * GST_OSSELEMENT (osssink)->channels; + guint8 *sbuf = g_new (guint8, to_handle); - if (!osssink->resync) { - guint8 *buf = g_new (guint8, to_handle); + memset (sbuf, (GST_OSSELEMENT (osssink)->width == 8) ? 0 : 128, + to_handle); + while (to_handle > 0) { + gint done = write (GST_OSSELEMENT (osssink)->fd, sbuf, + MIN (to_handle, osssink->chunk_size)); - memset (buf, (GST_OSSELEMENT (osssink)->width == 8) ? 0 : 128, - to_handle); - while (to_handle > 0) { - gint done = write (GST_OSSELEMENT (osssink)->fd, buf, - MIN (to_handle, osssink->chunk_size)); - - if (done == -1 && errno != EINTR) { - break; - } else { - to_handle -= done; - osssink->handled += done; - } + if (done == -1 && errno != EINTR) { + break; + } else { + to_handle -= done; + osssink->handled += done; } - g_free (buf); - } else { - /* Timestamps at start-of-stream (MPEG) or after seek (hey, - * again MPEG!) can be borken, therefore this hacklet. */ - osssink->handled += to_handle; } + g_free (sbuf); } } @@ -666,7 +655,6 @@ gst_osssink_change_state (GstElement * element) ioctl (GST_OSSELEMENT (osssink)->fd, SNDCTL_DSP_RESET, 0); gst_osselement_reset (GST_OSSELEMENT (osssink)); osssink->handled = 0; - osssink->resync = TRUE; break; default: break; diff --git a/sys/oss/gstosssink.h b/sys/oss/gstosssink.h index f484007..7542c8d 100644 --- a/sys/oss/gstosssink.h +++ b/sys/oss/gstosssink.h @@ -59,7 +59,6 @@ struct _GstOssSink { GstClock *provided_clock; GstClock *clock; - gboolean resync; gboolean sync; guint64 handled; -- 2.7.4