From 00e08a3f6eb6f504d9a42b7ee689d7c646de464a Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 3 Jul 2006 15:31:22 +0000 Subject: [PATCH] ext/libpng/gstpngdec.*: Implement buffer clipping/dropping using GstSegment. Original commit message from CVS: * ext/libpng/gstpngdec.c: (gst_pngdec_init), (user_info_callback), (buffer_clip), (user_end_callback), (gst_pngdec_chain), (gst_pngdec_sink_event), (gst_pngdec_change_state): * ext/libpng/gstpngdec.h: Implement buffer clipping/dropping using GstSegment. This provides accurate seeking. --- ChangeLog | 9 +++++++ ext/libpng/gstpngdec.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++---- ext/libpng/gstpngdec.h | 1 + 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 289874b..4de7d4d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2006-07-03 Edward Hervey + * ext/libpng/gstpngdec.c: (gst_pngdec_init), (user_info_callback), + (buffer_clip), (user_end_callback), (gst_pngdec_chain), + (gst_pngdec_sink_event), (gst_pngdec_change_state): + * ext/libpng/gstpngdec.h: + Implement buffer clipping/dropping using GstSegment. + This provides accurate seeking. + +2006-07-03 Edward Hervey + * gst/avi/gstavidemux.c: (gst_avi_demux_reset), (gst_avi_demux_read_subindexes), (gst_avi_demux_parse_stream), (gst_avi_demux_handle_seek), (gst_avi_demux_aggregated_flow), diff --git a/ext/libpng/gstpngdec.c b/ext/libpng/gstpngdec.c index 67f0878..d943d03 100644 --- a/ext/libpng/gstpngdec.c +++ b/ext/libpng/gstpngdec.c @@ -158,6 +158,8 @@ gst_pngdec_init (GstPngDec * pngdec) pngdec->in_timestamp = GST_CLOCK_TIME_NONE; pngdec->in_duration = GST_CLOCK_TIME_NONE; + + pngdec->segment = gst_segment_new (); } static void @@ -230,6 +232,29 @@ user_endrow_callback (png_structp png_ptr, png_bytep new_row, } } +static gboolean +buffer_clip (GstPngDec * dec, GstBuffer * buffer) +{ + gboolean res = TRUE; + gint64 cstart, cstop; + + if ((!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) || + (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) || + (dec->segment->format != GST_FORMAT_TIME)) + goto beach; + + if ((res = gst_segment_clip (dec->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer), + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer), + &cstart, &cstop))) { + GST_BUFFER_TIMESTAMP (buffer) = cstart; + GST_BUFFER_DURATION (buffer) = cstop - cstart; + } + +beach: + return res; +} + static void user_end_callback (png_structp png_ptr, png_infop info) { @@ -239,16 +264,25 @@ user_end_callback (png_structp png_ptr, png_infop info) GST_LOG_OBJECT (pngdec, "and we are done reading this image"); + if (!pngdec->buffer_out) + return; + if (GST_CLOCK_TIME_IS_VALID (pngdec->in_timestamp)) GST_BUFFER_TIMESTAMP (pngdec->buffer_out) = pngdec->in_timestamp; if (GST_CLOCK_TIME_IS_VALID (pngdec->in_duration)) GST_BUFFER_DURATION (pngdec->buffer_out) = pngdec->in_duration; - /* Push our buffer and then EOS if needed */ - GST_LOG_OBJECT (pngdec, "pushing buffer with ts=%" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (pngdec->buffer_out))); + /* buffer clipping */ + if (buffer_clip (pngdec, pngdec->buffer_out)) { + /* Push our buffer and then EOS if needed */ + GST_LOG_OBJECT (pngdec, "pushing buffer with ts=%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (pngdec->buffer_out))); - pngdec->ret = gst_pad_push (pngdec->srcpad, pngdec->buffer_out); + pngdec->ret = gst_pad_push (pngdec->srcpad, pngdec->buffer_out); + } else { + GST_LOG_OBJECT (pngdec, "dropped decoded buffer"); + gst_buffer_unref (pngdec->buffer_out); + } pngdec->buffer_out = NULL; if (pngdec->framed) { @@ -516,6 +550,7 @@ gst_pngdec_chain (GstPad * pad, GstBuffer * buffer) /* Progressive loading of the PNG image */ png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); + ret = pngdec->ret; /* And release the buffer */ gst_buffer_unref (buffer); @@ -559,9 +594,15 @@ gst_pngdec_sink_event (GstPad * pad, GstEvent * event) switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT:{ + gdouble rate; + gboolean update; + gint64 start, stop, position; GstFormat fmt; - gst_event_parse_new_segment (event, NULL, NULL, &fmt, NULL, NULL, NULL); + gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, + &position); + gst_segment_set_newsegment (pngdec->segment, update, rate, fmt, start, + stop, position); GST_LOG_OBJECT (pngdec, "NEWSEGMENT (%s)", gst_format_get_name (fmt)); if (fmt == GST_FORMAT_TIME) { pngdec->need_newsegment = FALSE; @@ -572,6 +613,14 @@ gst_pngdec_sink_event (GstPad * pad, GstEvent * event) } break; } + case GST_EVENT_FLUSH_START: + gst_pngdec_libpng_clear (pngdec); + res = gst_pad_event_default (pad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_pngdec_libpng_init (pngdec); + res = gst_pad_event_default (pad, event); + break; case GST_EVENT_EOS: GST_LOG_OBJECT (pngdec, "EOS"); gst_pngdec_libpng_clear (pngdec); @@ -679,6 +728,8 @@ gst_pngdec_change_state (GstElement * element, GstStateChange transition) gst_pngdec_libpng_init (pngdec); pngdec->need_newsegment = TRUE; pngdec->framed = FALSE; + pngdec->segment = gst_segment_new (); + gst_segment_init (pngdec->segment, GST_FORMAT_UNDEFINED); break; default: break; @@ -691,6 +742,10 @@ gst_pngdec_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_pngdec_libpng_clear (pngdec); + if (pngdec->segment) { + gst_segment_free (pngdec->segment); + pngdec->segment = NULL; + } break; default: break; diff --git a/ext/libpng/gstpngdec.h b/ext/libpng/gstpngdec.h index c16e7a9..5b11d5e 100644 --- a/ext/libpng/gstpngdec.h +++ b/ext/libpng/gstpngdec.h @@ -67,6 +67,7 @@ struct _GstPngDec gboolean framed; GstClockTime in_timestamp; GstClockTime in_duration; + GstSegment *segment; }; struct _GstPngDecClass -- 2.7.4