static void gst_wavpack_parse_finalize (GObject * object) { gst_wavpack_parse_reset (GST_WAVPACK_PARSE (object)); G_OBJECT_CLASS (parent_class)->finalize (object); }
static GstStateChangeReturn gst_wavpack_parse_change_state (GstElement * element, GstStateChange transition) { GstWavpackParse *wvparse = GST_WAVPACK_PARSE (element); GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: gst_segment_init (&wvparse->segment, GST_FORMAT_DEFAULT); wvparse->segment.last_stop = 0; default: break; } if (GST_ELEMENT_CLASS (parent_class)->change_state) ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_wavpack_parse_reset (wvparse); break; default: break; } return ret; }
static GstFlowReturn gst_wavpack_parse_chain (GstPad * pad, GstBuffer * buf) { GstWavpackParse *wvparse = GST_WAVPACK_PARSE (GST_PAD_PARENT (pad)); GstFlowReturn ret = GST_FLOW_OK; WavpackHeader wph; const guint8 *tmp_buf; if (!wvparse->adapter) { wvparse->adapter = gst_adapter_new (); } if (GST_BUFFER_IS_DISCONT (buf)) { gst_adapter_clear (wvparse->adapter); wvparse->discont = TRUE; } gst_adapter_push (wvparse->adapter, buf); if (gst_adapter_available (wvparse->adapter) < sizeof (WavpackHeader)) return ret; if (!gst_wavpack_parse_resync_adapter (wvparse->adapter)) return ret; tmp_buf = gst_adapter_peek (wvparse->adapter, sizeof (WavpackHeader)); gst_wavpack_read_header (&wph, (guint8 *) tmp_buf); while (gst_adapter_available (wvparse->adapter) >= wph.ckSize + 4 * 1 + 4) { GstBuffer *outbuf = gst_adapter_take_buffer (wvparse->adapter, wph.ckSize + 4 * 1 + 4); if (!outbuf) return GST_FLOW_ERROR; if (wvparse->srcpad == NULL) { if (!gst_wavpack_parse_create_src_pad (wvparse, outbuf, &wph)) { GST_ERROR_OBJECT (wvparse, "Failed to create src pad"); ret = GST_FLOW_ERROR; break; } } ret = gst_wavpack_parse_push_buffer (wvparse, outbuf, &wph); if (ret != GST_FLOW_OK) break; if (gst_adapter_available (wvparse->adapter) >= sizeof (WavpackHeader)) { tmp_buf = gst_adapter_peek (wvparse->adapter, sizeof (WavpackHeader)); if (!gst_wavpack_parse_resync_adapter (wvparse->adapter)) break; gst_wavpack_read_header (&wph, (guint8 *) tmp_buf); } } return ret; }
static gboolean gst_wavpack_parse_sink_event (GstPad * pad, GstEvent * event) { GstWavpackParse *parse; gboolean ret = TRUE; parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP:{ if (parse->adapter) { gst_adapter_clear (parse->adapter); } if (parse->pending_buffer) { gst_buffer_unref (parse->pending_buffer); parse->pending_buffer = NULL; parse->pending_offset = 0; } ret = gst_pad_push_event (parse->srcpad, event); break; } case GST_EVENT_NEWSEGMENT:{ parse->need_newsegment = TRUE; gst_event_unref (event); ret = TRUE; break; } case GST_EVENT_EOS:{ if (parse->adapter) { /* remove all bytes that are left in the adapter after EOS. They can't * be a complete Wavpack block and we can't do anything with them */ gst_adapter_clear (parse->adapter); } if (parse->pending_buffer) { gst_buffer_unref (parse->pending_buffer); parse->pending_buffer = NULL; parse->pending_offset = 0; } ret = gst_pad_push_event (parse->srcpad, event); break; } default:{ /* stream lock is recursive, should be fine for all events */ GST_PAD_STREAM_LOCK (pad); if (parse->srcpad == NULL) { parse->queued_events = g_list_append (parse->queued_events, event); } else { ret = gst_pad_push_event (parse->srcpad, event); } GST_PAD_STREAM_UNLOCK (pad); } } gst_object_unref (parse); return ret; }
static gboolean gst_wavpack_parse_src_event (GstPad * pad, GstEvent * event) { GstWavpackParse *parse; gboolean ret; parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad)); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: ret = gst_wavpack_parse_handle_seek_event (parse, event); break; default: ret = gst_pad_event_default (pad, event); break; } gst_object_unref (parse); return ret; }
static gboolean gst_wavpack_parse_src_query (GstPad * pad, GstQuery * query) { GstWavpackParse *parse = GST_WAVPACK_PARSE (gst_pad_get_parent (pad)); GstFormat format; gboolean ret = FALSE; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION:{ gint64 cur; guint rate; GST_OBJECT_LOCK (parse); cur = parse->segment.last_stop; rate = parse->samplerate; GST_OBJECT_UNLOCK (parse); if (rate == 0) { GST_DEBUG_OBJECT (parse, "haven't read header yet"); break; } gst_query_parse_position (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: cur = gst_util_uint64_scale_int (cur, GST_SECOND, rate); gst_query_set_position (query, GST_FORMAT_TIME, cur); ret = TRUE; break; case GST_FORMAT_DEFAULT: gst_query_set_position (query, GST_FORMAT_DEFAULT, cur); ret = TRUE; break; default: GST_DEBUG_OBJECT (parse, "cannot handle position query in " "%s format. Forwarding upstream.", gst_format_get_name (format)); ret = gst_pad_query_default (pad, query); break; } break; } case GST_QUERY_DURATION:{ gint64 len; guint rate; GST_OBJECT_LOCK (parse); rate = parse->samplerate; len = parse->total_samples; GST_OBJECT_UNLOCK (parse); if (rate == 0) { GST_DEBUG_OBJECT (parse, "haven't read header yet"); break; } gst_query_parse_duration (query, &format, NULL); switch (format) { case GST_FORMAT_TIME: if (len != G_GINT64_CONSTANT (-1)) len = gst_util_uint64_scale_int (len, GST_SECOND, rate); gst_query_set_duration (query, GST_FORMAT_TIME, len); ret = TRUE; break; case GST_FORMAT_DEFAULT: gst_query_set_duration (query, GST_FORMAT_DEFAULT, len); ret = TRUE; break; default: GST_DEBUG_OBJECT (parse, "cannot handle duration query in " "%s format. Forwarding upstream.", gst_format_get_name (format)); ret = gst_pad_query_default (pad, query); break; } break; } case GST_QUERY_SEEKING:{ gst_query_parse_seeking (query, &format, NULL, NULL, NULL); if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) { gboolean seekable; gint64 duration = -1; /* only fails if we didn't read the headers yet and can't say * anything about our seeking capabilities */ if (!gst_pad_query_duration (pad, &format, &duration)) break; /* can't seek in streaming mode yet */ GST_OBJECT_LOCK (parse); seekable = (parse->adapter == NULL); GST_OBJECT_UNLOCK (parse); gst_query_set_seeking (query, format, seekable, 0, duration); ret = TRUE; } break; } default:{ ret = gst_pad_query_default (pad, query); break; } } gst_object_unref (parse); return ret; }
static void gst_wavpack_parse_loop (GstElement * element) { GstWavpackParse *parse = GST_WAVPACK_PARSE (element); GstFlowReturn flow_ret; WavpackHeader header = { {0,}, 0, }; GstBuffer *buf = NULL; flow_ret = gst_wavpack_parse_resync_loop (parse, &header); if (flow_ret != GST_FLOW_OK) goto pause; GST_LOG_OBJECT (parse, "Read header at offset %" G_GINT64_FORMAT ": chunk size = %u+8", parse->current_offset, header.ckSize); buf = gst_wavpack_parse_pull_buffer (parse, parse->current_offset, header.ckSize + 8, &flow_ret); if (flow_ret != GST_FLOW_OK) goto pause; if (parse->srcpad == NULL) { if (!gst_wavpack_parse_create_src_pad (parse, buf, &header)) { GST_ERROR_OBJECT (parse, "Failed to create src pad"); flow_ret = GST_FLOW_ERROR; goto pause; } } if (header.flags & INITIAL_BLOCK) gst_wavpack_parse_index_append_entry (parse, parse->current_offset, header.block_index, header.block_samples); flow_ret = gst_wavpack_parse_push_buffer (parse, buf, &header); if (flow_ret != GST_FLOW_OK) goto pause; return; pause: { const gchar *reason = gst_flow_get_name (flow_ret); GST_LOG_OBJECT (parse, "pausing task, reason %s", reason); gst_pad_pause_task (parse->sinkpad); if (GST_FLOW_IS_FATAL (flow_ret) || flow_ret == GST_FLOW_NOT_LINKED) { if (flow_ret == GST_FLOW_UNEXPECTED && parse->srcpad) { if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) { GstClockTime stop; GST_LOG_OBJECT (parse, "Sending segment done"); if ((stop = parse->segment.stop) == -1) stop = parse->segment.duration; gst_element_post_message (GST_ELEMENT_CAST (parse), gst_message_new_segment_done (GST_OBJECT_CAST (parse), parse->segment.format, stop)); } else { GST_LOG_OBJECT (parse, "Sending EOS, at end of stream"); gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); } } else { GST_ELEMENT_ERROR (parse, STREAM, FAILED, (_("Internal data stream error.")), ("stream stopped, reason %s", reason)); if (parse->srcpad) gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); } } return; } }