static GstStateChangeReturn gst_pngdec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret; GstPngDec *pngdec; pngdec = GST_PNGDEC (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_pngdec_libpng_init (pngdec); pngdec->need_newsegment = TRUE; pngdec->framed = FALSE; pngdec->ret = GST_FLOW_OK; gst_segment_init (&pngdec->segment, GST_FORMAT_UNDEFINED); break; default: break; } ret = parent_class->change_state (element, transition); if (ret != GST_STATE_CHANGE_SUCCESS) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_pngdec_libpng_clear (pngdec); break; default: break; } return ret; }
static gboolean gst_pngdec_sink_event (GstPad * pad, GstEvent * event) { GstPngDec *pngdec; gboolean res; pngdec = GST_PNGDEC (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT:{ gdouble rate, arate; gboolean update; gint64 start, stop, position; GstFormat fmt; gst_event_parse_new_segment_full (event, &update, &rate, &arate, &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)); if (fmt == GST_FORMAT_TIME) { pngdec->need_newsegment = FALSE; res = gst_pad_push_event (pngdec->srcpad, event); } else { gst_event_unref (event); res = TRUE; } break; } case GST_EVENT_FLUSH_STOP: { gst_pngdec_libpng_clear (pngdec); gst_pngdec_libpng_init (pngdec); 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; } case GST_EVENT_EOS: { GST_LOG_OBJECT (pngdec, "EOS"); gst_pngdec_libpng_clear (pngdec); pngdec->ret = GST_FLOW_UNEXPECTED; res = gst_pad_push_event (pngdec->srcpad, event); break; } default: res = gst_pad_push_event (pngdec->srcpad, event); break; } gst_object_unref (pngdec); return res; }
/* Clean up the libpng structures */ static gboolean gst_pngdec_flush (GstVideoDecoder * decoder) { gst_pngdec_libpng_clear ((GstPngDec *) decoder); gst_pngdec_libpng_init ((GstPngDec *) decoder); return TRUE; }
/* Clean up the libpng structures */ static gboolean gst_pngdec_reset (GstVideoDecoder * decoder, gboolean hard) { gst_pngdec_libpng_clear ((GstPngDec *) decoder); gst_pngdec_libpng_init ((GstPngDec *) decoder); return TRUE; }
static gboolean gst_pngdec_start (GstVideoDecoder * decoder) { GstPngDec *pngdec = (GstPngDec *) decoder; gst_pngdec_libpng_init (pngdec); return TRUE; }
static gboolean gst_pngdec_start (GstVideoDecoder * decoder) { GstPngDec *pngdec = (GstPngDec *) decoder; gst_video_decoder_set_packetized (GST_VIDEO_DECODER (pngdec), FALSE); gst_pngdec_libpng_init (pngdec); return TRUE; }
static GstFlowReturn gst_pngdec_chain (GstPad * pad, GstBuffer * buffer) { GstPngDec *pngdec; GstFlowReturn ret = GST_FLOW_OK; pngdec = GST_PNGDEC (gst_pad_get_parent (pad)); GST_LOG_OBJECT (pngdec, "Got buffer, size=%u", GST_BUFFER_SIZE (buffer)); if (G_UNLIKELY (!pngdec->setup)) goto not_configured; /* Something is going wrong in our callbacks */ 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; } /* Let libpng come back here on error */ if (setjmp (png_jmpbuf (pngdec->png))) { GST_WARNING_OBJECT (pngdec, "error during decoding"); ret = GST_FLOW_ERROR; goto beach; } pngdec->in_timestamp = GST_BUFFER_TIMESTAMP (buffer); pngdec->in_duration = GST_BUFFER_DURATION (buffer); /* Progressive loading of the PNG image */ png_process_data (pngdec->png, pngdec->info, GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer)); if (pngdec->image_ready) { if (pngdec->framed) { /* Reset ourselves for the next frame */ gst_pngdec_libpng_clear (pngdec); gst_pngdec_libpng_init (pngdec); GST_LOG_OBJECT (pngdec, "setting up callbacks for next frame"); png_set_progressive_read_fn (pngdec->png, pngdec, user_info_callback, user_endrow_callback, user_end_callback); } else { GST_LOG_OBJECT (pngdec, "sending EOS"); pngdec->ret = gst_pad_push_event (pngdec->srcpad, gst_event_new_eos ()); } pngdec->image_ready = FALSE; } /* grab new return code */ ret = pngdec->ret; /* And release the buffer */ gst_buffer_unref (buffer); beach: gst_object_unref (pngdec); return ret; /* ERRORS */ not_configured: { GST_LOG_OBJECT (pngdec, "we are not configured yet"); ret = GST_FLOW_WRONG_STATE; goto beach; } }