ext/libpng/gstpngdec.*: Use statically allocated segment instead of leaking.

Original commit message from CVS:
* ext/libpng/gstpngdec.c: (gst_pngdec_init), (buffer_clip),
(gst_pngdec_caps_create_and_set), (gst_pngdec_task),
(gst_pngdec_chain), (gst_pngdec_sink_event),
(gst_pngdec_libpng_init), (gst_pngdec_change_state),
(gst_pngdec_sink_activate_push):
* ext/libpng/gstpngdec.h:
Use statically allocated segment instead of leaking.
Various cleanups.
Fix flush and seek handling.
This commit is contained in:
Wim Taymans 2006-07-17 10:22:54 +00:00
parent f6a274239a
commit cc350794fb
3 changed files with 114 additions and 71 deletions

View file

@ -1,3 +1,15 @@
2006-07-17 Wim Taymans <wim@fluendo.com>
* ext/libpng/gstpngdec.c: (gst_pngdec_init), (buffer_clip),
(gst_pngdec_caps_create_and_set), (gst_pngdec_task),
(gst_pngdec_chain), (gst_pngdec_sink_event),
(gst_pngdec_libpng_init), (gst_pngdec_change_state),
(gst_pngdec_sink_activate_push):
* ext/libpng/gstpngdec.h:
Use statically allocated segment instead of leaking.
Various cleanups.
Fix flush and seek handling.
2006-07-16 Wim Taymans <wim@fluendo.com> 2006-07-16 Wim Taymans <wim@fluendo.com>
* gst/rtp/Makefile.am: * gst/rtp/Makefile.am:

View file

@ -159,7 +159,7 @@ gst_pngdec_init (GstPngDec * pngdec)
pngdec->in_timestamp = GST_CLOCK_TIME_NONE; pngdec->in_timestamp = GST_CLOCK_TIME_NONE;
pngdec->in_duration = GST_CLOCK_TIME_NONE; pngdec->in_duration = GST_CLOCK_TIME_NONE;
pngdec->segment = gst_segment_new (); gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
} }
static void static void
@ -240,10 +240,10 @@ buffer_clip (GstPngDec * dec, GstBuffer * buffer)
if ((!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) || if ((!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) ||
(!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) || (!GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buffer))) ||
(dec->segment->format != GST_FORMAT_TIME)) (dec->segment.format != GST_FORMAT_TIME))
goto beach; goto beach;
if ((res = gst_segment_clip (dec->segment, GST_FORMAT_TIME, if ((res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME,
GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer),
GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer), GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer),
&cstart, &cstop))) { &cstart, &cstop))) {
@ -403,7 +403,7 @@ gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
default: default:
GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL), GST_ELEMENT_ERROR (pngdec, STREAM, NOT_IMPLEMENTED, (NULL),
("pngdec does not support this color type")); ("pngdec does not support this color type"));
ret = GST_FLOW_ERROR; ret = GST_FLOW_NOT_SUPPORTED;
goto beach; goto beach;
} }
@ -420,9 +420,8 @@ gst_pngdec_caps_create_and_set (GstPngDec * pngdec)
gst_caps_unref (caps); gst_caps_unref (caps);
gst_object_unref (templ); gst_object_unref (templ);
if (!gst_pad_set_caps (pngdec->srcpad, res)) { if (!gst_pad_set_caps (pngdec->srcpad, res))
ret = GST_FLOW_ERROR; ret = GST_FLOW_NOT_NEGOTIATED;
}
GST_DEBUG_OBJECT (pngdec, "our caps %" GST_PTR_FORMAT, res); GST_DEBUG_OBJECT (pngdec, "our caps %" GST_PTR_FORMAT, res);
@ -505,13 +504,15 @@ gst_pngdec_task (GstPad * pad)
return; return;
pause: pause:
GST_LOG_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret)); {
gst_pad_pause_task (pngdec->sinkpad); GST_LOG_OBJECT (pngdec, "pausing task, reason %s", gst_flow_get_name (ret));
if (GST_FLOW_IS_FATAL (ret)) { gst_pad_pause_task (pngdec->sinkpad);
gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); if (GST_FLOW_IS_FATAL (ret)) {
GST_ELEMENT_ERROR (pngdec, STREAM, FAILED, gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ());
(_("Internal data stream error.")), GST_ELEMENT_ERROR (pngdec, STREAM, FAILED,
("stream stopped, reason %s", gst_flow_get_name (ret))); (_("Internal data stream error.")),
("stream stopped, reason %s", gst_flow_get_name (ret)));
}
} }
} }
@ -521,25 +522,23 @@ gst_pngdec_chain (GstPad * pad, GstBuffer * buffer)
GstPngDec *pngdec; GstPngDec *pngdec;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
pngdec = GST_PNGDEC (GST_OBJECT_PARENT (pad)); pngdec = GST_PNGDEC (gst_pad_get_parent (pad));
GST_LOG_OBJECT (pngdec, "Got buffer, size=%u", GST_BUFFER_SIZE (buffer)); GST_LOG_OBJECT (pngdec, "Got buffer, size=%u", GST_BUFFER_SIZE (buffer));
if (!pngdec->setup) { if (G_UNLIKELY (!pngdec->setup))
GST_LOG ("we are not configured yet"); goto not_configured;
ret = GST_FLOW_WRONG_STATE;
goto beach;
}
/* Something is going wrong in our callbacks */ /* Something is going wrong in our callbacks */
if (pngdec->ret != GST_FLOW_OK) { ret = pngdec->ret;
ret = pngdec->ret; if (G_UNLIKELY (ret != GST_FLOW_OK)) {
GST_WARNING_OBJECT (pngdec, "we have a pending return code of %d", ret);
goto beach; goto beach;
} }
/* Let libpng come back here on error */ /* Let libpng come back here on error */
if (setjmp (png_jmpbuf (pngdec->png))) { if (setjmp (png_jmpbuf (pngdec->png))) {
GST_WARNING ("error during decoding"); GST_WARNING_OBJECT (pngdec, "error during decoding");
ret = GST_FLOW_ERROR; ret = GST_FLOW_ERROR;
goto beach; goto beach;
} }
@ -550,13 +549,25 @@ gst_pngdec_chain (GstPad * pad, GstBuffer * buffer)
/* Progressive loading of the PNG image */ /* Progressive loading of the PNG image */
png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer), png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer),
GST_BUFFER_SIZE (buffer)); GST_BUFFER_SIZE (buffer));
/* grab new return code */
ret = pngdec->ret; ret = pngdec->ret;
/* And release the buffer */ /* And release the buffer */
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
beach: beach:
gst_object_unref (pngdec);
return ret; return ret;
/* ERRORS */
not_configured:
{
GST_LOG_OBJECT (pngdec, "we are not configured yet");
ret = GST_FLOW_WRONG_STATE;
goto beach;
}
} }
static gboolean static gboolean
@ -594,40 +605,49 @@ gst_pngdec_sink_event (GstPad * pad, GstEvent * event)
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:{ case GST_EVENT_NEWSEGMENT:{
gdouble rate; gdouble rate, arate;
gboolean update; gboolean update;
gint64 start, stop, position; gint64 start, stop, position;
GstFormat fmt; GstFormat fmt;
gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
&position); &start, &stop, &position);
gst_segment_set_newsegment (pngdec->segment, update, rate, fmt, start,
stop, position); gst_segment_set_newsegment_full (&pngdec->segment, update, rate, arate,
fmt, start, stop, position);
GST_LOG_OBJECT (pngdec, "NEWSEGMENT (%s)", gst_format_get_name (fmt)); GST_LOG_OBJECT (pngdec, "NEWSEGMENT (%s)", gst_format_get_name (fmt));
if (fmt == GST_FORMAT_TIME) { if (fmt == GST_FORMAT_TIME) {
pngdec->need_newsegment = FALSE; pngdec->need_newsegment = FALSE;
res = gst_pad_event_default (pad, event); res = gst_pad_push_event (pngdec->srcpad, event);
} else { } else {
gst_event_unref (event); gst_event_unref (event);
res = TRUE; res = TRUE;
} }
break; break;
} }
case GST_EVENT_FLUSH_START:
gst_pngdec_libpng_clear (pngdec);
res = gst_pad_event_default (pad, event);
break;
case GST_EVENT_FLUSH_STOP: case GST_EVENT_FLUSH_STOP:
{
gst_pngdec_libpng_clear (pngdec);
gst_pngdec_libpng_init (pngdec); gst_pngdec_libpng_init (pngdec);
res = gst_pad_event_default (pad, event); png_set_progressive_read_fn (pngdec->png, pngdec,
user_info_callback, user_endrow_callback, user_end_callback);
pngdec->ret = GST_FLOW_OK;
gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
res = gst_pad_push_event (pngdec->srcpad, event);
break; break;
}
case GST_EVENT_EOS: case GST_EVENT_EOS:
{
GST_LOG_OBJECT (pngdec, "EOS"); GST_LOG_OBJECT (pngdec, "EOS");
gst_pngdec_libpng_clear (pngdec); gst_pngdec_libpng_clear (pngdec);
res = gst_pad_event_default (pad, event); pngdec->ret = GST_FLOW_UNEXPECTED;
res = gst_pad_push_event (pngdec->srcpad, event);
break; break;
}
default: default:
res = gst_pad_event_default (pad, event); res = gst_pad_push_event (pngdec->srcpad, event);
break; break;
} }
@ -679,40 +699,51 @@ gst_pngdec_libpng_init (GstPngDec * pngdec)
{ {
g_return_val_if_fail (GST_IS_PNGDEC (pngdec), FALSE); g_return_val_if_fail (GST_IS_PNGDEC (pngdec), FALSE);
if (pngdec->setup) { if (pngdec->setup)
goto beach; return TRUE;
}
GST_LOG ("init libpng structures");
/* initialize png struct stuff */ /* initialize png struct stuff */
pngdec->png = png_create_read_struct (PNG_LIBPNG_VER_STRING, pngdec->png = png_create_read_struct (PNG_LIBPNG_VER_STRING,
(png_voidp) NULL, user_error_fn, user_warning_fn); (png_voidp) NULL, user_error_fn, user_warning_fn);
if (pngdec->png == NULL) { if (pngdec->png == NULL)
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL), goto init_failed;
("Failed to initialize png structure"));
goto beach;
}
pngdec->info = png_create_info_struct (pngdec->png); pngdec->info = png_create_info_struct (pngdec->png);
if (pngdec->info == NULL) { if (pngdec->info == NULL)
gst_pngdec_libpng_clear (pngdec); goto info_failed;
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
("Failed to initialize info structure"));
goto beach;
}
pngdec->endinfo = png_create_info_struct (pngdec->png); pngdec->endinfo = png_create_info_struct (pngdec->png);
if (pngdec->endinfo == NULL) { if (pngdec->endinfo == NULL)
gst_pngdec_libpng_clear (pngdec); goto endinfo_failed;
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
("Failed to initialize endinfo structure"));
goto beach;
}
pngdec->setup = TRUE; pngdec->setup = TRUE;
beach: return TRUE;
return pngdec->setup;
/* ERRORS */
init_failed:
{
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
("Failed to initialize png structure"));
return FALSE;
}
info_failed:
{
gst_pngdec_libpng_clear (pngdec);
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
("Failed to initialize info structure"));
return FALSE;
}
endinfo_failed:
{
gst_pngdec_libpng_clear (pngdec);
GST_ELEMENT_ERROR (pngdec, LIBRARY, INIT, (NULL),
("Failed to initialize endinfo structure"));
return FALSE;
}
} }
static GstStateChangeReturn static GstStateChangeReturn
@ -728,8 +759,8 @@ gst_pngdec_change_state (GstElement * element, GstStateChange transition)
gst_pngdec_libpng_init (pngdec); gst_pngdec_libpng_init (pngdec);
pngdec->need_newsegment = TRUE; pngdec->need_newsegment = TRUE;
pngdec->framed = FALSE; pngdec->framed = FALSE;
pngdec->segment = gst_segment_new (); pngdec->ret = GST_FLOW_OK;
gst_segment_init (pngdec->segment, GST_FORMAT_UNDEFINED); gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED);
break; break;
default: default:
break; break;
@ -742,10 +773,6 @@ gst_pngdec_change_state (GstElement * element, GstStateChange transition)
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
gst_pngdec_libpng_clear (pngdec); gst_pngdec_libpng_clear (pngdec);
if (pngdec->segment) {
gst_segment_free (pngdec->segment);
pngdec->segment = NULL;
}
break; break;
default: default:
break; break;
@ -766,18 +793,21 @@ gst_pngdec_sink_activate_push (GstPad * sinkpad, gboolean active)
if (active) { if (active) {
/* Let libpng come back here on error */ /* Let libpng come back here on error */
if (setjmp (png_jmpbuf (pngdec->png))) { if (setjmp (png_jmpbuf (pngdec->png)))
GST_LOG ("failed setting up libpng jumb"); goto setup_failed;
gst_pngdec_libpng_clear (pngdec);
return FALSE;
}
GST_LOG ("setting up progressive loading callbacks"); GST_LOG ("setting up progressive loading callbacks");
png_set_progressive_read_fn (pngdec->png, pngdec, png_set_progressive_read_fn (pngdec->png, pngdec,
user_info_callback, user_endrow_callback, user_end_callback); user_info_callback, user_endrow_callback, user_end_callback);
} }
return TRUE; return TRUE;
setup_failed:
{
GST_LOG ("failed setting up libpng jmpbuf");
gst_pngdec_libpng_clear (pngdec);
return FALSE;
}
} }
/* this function gets called when we activate ourselves in pull mode. /* this function gets called when we activate ourselves in pull mode.

View file

@ -67,7 +67,8 @@ struct _GstPngDec
gboolean framed; gboolean framed;
GstClockTime in_timestamp; GstClockTime in_timestamp;
GstClockTime in_duration; GstClockTime in_duration;
GstSegment *segment;
GstSegment segment;
}; };
struct _GstPngDecClass struct _GstPngDecClass