static gboolean gst_gdk_pixbuf_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstFlowReturn res = GST_FLOW_OK; gboolean ret = TRUE, forward = TRUE; GstGdkPixbufDec *pixbuf; pixbuf = GST_GDK_PIXBUF_DEC (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); ret = gst_gdk_pixbuf_dec_sink_setcaps (pixbuf, caps); forward = FALSE; break; } case GST_EVENT_EOS: if (pixbuf->pixbuf_loader != NULL) { gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); res = gst_gdk_pixbuf_dec_flush (pixbuf); g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); pixbuf->pixbuf_loader = NULL; /* as long as we don't have flow returns for event functions we need * to post an error here, or the application might never know that * things failed */ if (res != GST_FLOW_OK && res != GST_FLOW_FLUSHING) { GST_ELEMENT_ERROR (pixbuf, STREAM, FAILED, (NULL), ("Flow: %s", gst_flow_get_name (res))); forward = FALSE; ret = FALSE; } } break; case GST_EVENT_SEGMENT: case GST_EVENT_FLUSH_STOP: if (pixbuf->pixbuf_loader != NULL) { gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); pixbuf->pixbuf_loader = NULL; } break; default: break; } if (forward) { ret = gst_pad_event_default (pad, parent, event); } else { gst_event_unref (event); } return ret; }
static GstFlowReturn gst_gdk_pixbuf_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstGdkPixbufDec *filter; GstFlowReturn ret = GST_FLOW_OK; GError *error = NULL; GstClockTime timestamp; GstMapInfo map; filter = GST_GDK_PIXBUF_DEC (parent); timestamp = GST_BUFFER_TIMESTAMP (buf); if (GST_CLOCK_TIME_IS_VALID (timestamp)) filter->last_timestamp = timestamp; GST_LOG_OBJECT (filter, "buffer with ts: %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); if (filter->pixbuf_loader == NULL) filter->pixbuf_loader = gdk_pixbuf_loader_new (); gst_buffer_map (buf, &map, GST_MAP_READ); GST_LOG_OBJECT (filter, "Writing buffer size %d", (gint) map.size); if (!gdk_pixbuf_loader_write (filter->pixbuf_loader, map.data, map.size, &error)) goto error; /* packetised mode? *//* FIXME: shouln't this be fps_d != 0, since 0/1 * might be packetised mode but variable framerate */ if (filter->in_fps_n != 0) { gdk_pixbuf_loader_close (filter->pixbuf_loader, NULL); ret = gst_gdk_pixbuf_dec_flush (filter); g_object_unref (filter->pixbuf_loader); filter->pixbuf_loader = NULL; } gst_buffer_unmap (buf, &map); gst_buffer_unref (buf); return ret; /* ERRORS */ error: { GST_ELEMENT_ERROR (filter, STREAM, DECODE, (NULL), ("gdk_pixbuf_loader_write error: %s", error->message)); g_error_free (error); gst_buffer_unmap (buf, &map); gst_buffer_unref (buf); return GST_FLOW_ERROR; } }
static GstStateChangeReturn gst_gdk_pixbuf_dec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstGdkPixbufDec *dec = GST_GDK_PIXBUF_DEC (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: /* default to single image mode, setcaps function might not be called */ dec->in_fps_n = 0; dec->in_fps_d = 1; gst_video_info_init (&dec->info); break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: dec->in_fps_n = 0; dec->in_fps_d = 0; if (dec->pool) { gst_buffer_pool_set_active (dec->pool, FALSE); gst_object_replace ((GstObject **) & dec->pool, NULL); } g_list_free_full (dec->pending_events, (GDestroyNotify) gst_event_unref); dec->pending_events = NULL; if (dec->pixbuf_loader != NULL) { gdk_pixbuf_loader_close (dec->pixbuf_loader, NULL); g_object_unref (G_OBJECT (dec->pixbuf_loader)); dec->pixbuf_loader = NULL; } break; default: break; } return ret; }
static gboolean gst_gdk_pixbuf_dec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) { GstFlowReturn res = GST_FLOW_OK; gboolean ret = TRUE, forward = TRUE; GstGdkPixbufDec *pixbuf; pixbuf = GST_GDK_PIXBUF_DEC (parent); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_CAPS: { GstCaps *caps; gst_event_parse_caps (event, &caps); ret = gst_gdk_pixbuf_dec_sink_setcaps (pixbuf, caps); forward = FALSE; break; } case GST_EVENT_EOS: if (pixbuf->pixbuf_loader != NULL) { gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); res = gst_gdk_pixbuf_dec_flush (pixbuf); g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); pixbuf->pixbuf_loader = NULL; /* as long as we don't have flow returns for event functions we need * to post an error here, or the application might never know that * things failed */ if (res != GST_FLOW_OK && res != GST_FLOW_FLUSHING && res != GST_FLOW_EOS && res != GST_FLOW_NOT_LINKED) { GST_ELEMENT_ERROR (pixbuf, STREAM, FAILED, (NULL), ("Flow: %s", gst_flow_get_name (res))); forward = FALSE; ret = FALSE; } } break; case GST_EVENT_FLUSH_STOP: g_list_free_full (pixbuf->pending_events, (GDestroyNotify) gst_event_unref); pixbuf->pending_events = NULL; /* Fall through */ case GST_EVENT_SEGMENT: { const GstSegment *segment; gst_event_parse_segment (event, &segment); if (segment->format == GST_FORMAT_BYTES) pixbuf->packetized = FALSE; else pixbuf->packetized = TRUE; if (pixbuf->pixbuf_loader != NULL) { gdk_pixbuf_loader_close (pixbuf->pixbuf_loader, NULL); g_object_unref (G_OBJECT (pixbuf->pixbuf_loader)); pixbuf->pixbuf_loader = NULL; } break; } default: break; } if (forward) { if (!gst_pad_has_current_caps (pixbuf->srcpad) && GST_EVENT_IS_SERIALIZED (event) && GST_EVENT_TYPE (event) > GST_EVENT_CAPS && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP && GST_EVENT_TYPE (event) != GST_EVENT_EOS) { ret = TRUE; pixbuf->pending_events = g_list_prepend (pixbuf->pending_events, event); } else { ret = gst_pad_event_default (pad, parent, event); } } else { gst_event_unref (event); } return ret; }