/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- * Copyright (C) <2006> Nokia Corporation, Stefan Kost <stefan.kost@nokia.com>.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* <title>Example launch line</title>
* <para>
* <programlisting>
- * gst-launch filesrc location=sine.wav ! queue ! wavparse ! audioconvert ! alsasink
+ * gst-launch filesrc sine.wav ! wavparse ! audioconvert ! alsasink
* </programlisting>
* Read a wav file and output to the soundcard using the ALSA element. The
* wav file is assumed to contain raw uncompressed samples.
* </para>
- * <para>
- * <programlisting>
- * gst-launch gnomevfssrc location=http://www.example.org/sine.wav ! wavparse ! audioconvert ! alsasink
- * </programlisting>
- * Stream data from
- * </para>
- *
* </refsect2>
*
* Last reviewed on 2006-03-03 (0.10.3)
#include "gst/riff/riff-media.h"
#include <gst/gst-i18n-plugin.h>
-#ifndef G_MAXUINT32
-#define G_MAXUINT32 0xffffffff
-#endif
-
GST_DEBUG_CATEGORY_STATIC (wavparse_debug);
#define GST_CAT_DEFAULT (wavparse_debug)
static void gst_wavparse_base_init (gpointer g_class);
static void gst_wavparse_class_init (GstWavParseClass * klass);
static void gst_wavparse_init (GstWavParse * wavparse);
-static void gst_wavparse_dispose (GObject * object);
static gboolean gst_wavparse_sink_activate (GstPad * sinkpad);
static gboolean gst_wavparse_sink_activate_pull (GstPad * sinkpad,
gboolean active);
static gboolean gst_wavparse_send_event (GstElement * element,
GstEvent * event);
-static GstFlowReturn gst_wavparse_chain (GstPad * pad, GstBuffer * buf);
static GstStateChangeReturn gst_wavparse_change_state (GstElement * element,
GstStateChange transition);
static void gst_wavparse_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
-static const GstElementDetails gst_wavparse_details =
-GST_ELEMENT_DETAILS ("WAV audio demuxer",
- "Codec/Demuxer/Audio",
- "Parse a .wav file into raw audio",
- "Erik Walthinsen <omega@cse.ogi.edu>");
-
static GstStaticPadTemplate sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("wavparse_sink",
GST_PAD_SINK,
gst_wavparse_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+ GstPadTemplate *templ;
+ static GstElementDetails gst_wavparse_details =
+ GST_ELEMENT_DETAILS ("WAV audio demuxer",
+ "Codec/Demuxer/Audio",
+ "Parse a .wav file into raw audio",
+ "Erik Walthinsen <omega@cse.ogi.edu>");
- /* register src pads */
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&sink_template_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template_factory));
gst_element_class_set_details (element_class, &gst_wavparse_details);
+
+ /* register src pads */
+ templ = gst_static_pad_template_get (&sink_template_factory);
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_object_unref (templ);
+ templ = gst_static_pad_template_get (&src_template_factory);
+ gst_element_class_add_pad_template (element_class, templ);
+ gst_object_unref (templ);
}
static void
parent_class = g_type_class_peek_parent (klass);
object_class->get_property = gst_wavparse_get_property;
- object_class->dispose = gst_wavparse_dispose;
gstelement_class->change_state = gst_wavparse_change_state;
gstelement_class->send_event = gst_wavparse_send_event;
-}
-
-
-static void
-gst_wavparse_dispose (GObject * object)
-{
- GST_DEBUG ("WAV: Dispose\n");
- GstWavParse *wav = GST_WAVPARSE (object);
- if (wav->adapter) {
- g_object_unref (wav->adapter);
- wav->adapter = NULL;
- }
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
+ GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
}
-
static void
gst_wavparse_reset (GstWavParse * wavparse)
{
wavparse->dataleft = 0;
wavparse->datasize = 0;
wavparse->datastart = 0;
- wavparse->got_fmt = FALSE;
- wavparse->first = TRUE;
-
- if (wavparse->seek_event)
- gst_event_unref (wavparse->seek_event);
- wavparse->seek_event = NULL;
/* we keep the segment info in time */
gst_segment_init (&wavparse->segment, GST_FORMAT_TIME);
GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate));
gst_pad_set_activatepull_function (wavparse->sinkpad,
GST_DEBUG_FUNCPTR (gst_wavparse_sink_activate_pull));
- gst_pad_set_chain_function (wavparse->sinkpad,
- GST_DEBUG_FUNCPTR (gst_wavparse_chain));
gst_element_add_pad (GST_ELEMENT (wavparse), wavparse->sinkpad);
-
- /* src, will be created later */
- wavparse->srcpad = NULL;
}
static void
GST_DEBUG_FUNCPTR (gst_wavparse_pad_query));
gst_pad_set_event_function (wavparse->srcpad,
GST_DEBUG_FUNCPTR (gst_wavparse_srcpad_event));
-
- GST_DEBUG_OBJECT (wavparse, "srcpad created");
}
static void
}
}
-
-
#if 0
static void
gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
g_object_notify (G_OBJECT (wavparse), "metadata");
}
+#endif
+#if 0
static void
gst_wavparse_parse_cues (GstWavParse * wavparse, int len)
{
g_object_notify (G_OBJECT (wavparse), "metadata");
}
+#endif
+
+static gboolean
+gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
+{
+ guint32 doctype;
+
+ if (!gst_riff_parse_file_header (element, buf, &doctype))
+ return FALSE;
+
+ if (doctype != GST_RIFF_RIFF_WAVE)
+ goto not_wav;
+
+ return TRUE;
+
+ /* ERRORS */
+not_wav:
+ {
+ GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
+ ("File is not an WAVE file: %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (doctype)));
+ return FALSE;
+ }
+}
+static GstFlowReturn
+gst_wavparse_stream_init (GstWavParse * wav)
+{
+ GstFlowReturn res;
+ GstBuffer *buf = NULL;
+
+ if ((res = gst_pad_pull_range (wav->sinkpad,
+ wav->offset, 12, &buf)) != GST_FLOW_OK)
+ return res;
+ else if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), buf))
+ return GST_FLOW_ERROR;
+
+ wav->offset += 12;
+
+ return GST_FLOW_OK;
+}
+
+#if 0
/* Read 'fmt ' header */
static gboolean
gst_wavparse_fmt (GstWavParse * wav)
}
#endif
-
-
-static gboolean
-gst_wavparse_parse_file_header (GstElement * element, GstBuffer * buf)
-{
- guint32 doctype;
-
- if (!gst_riff_parse_file_header (element, buf, &doctype))
- return FALSE;
-
- if (doctype != GST_RIFF_RIFF_WAVE)
- goto not_wav;
-
- return TRUE;
-
- /* ERRORS */
-not_wav:
- {
- GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL),
- ("File is not an WAVE file: %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (doctype)));
- return FALSE;
- }
-}
-
-static GstFlowReturn
-gst_wavparse_stream_init (GstWavParse * wav)
-{
- GstFlowReturn res;
- GstBuffer *buf = NULL;
-
- if ((res = gst_pad_pull_range (wav->sinkpad,
- wav->offset, 12, &buf)) != GST_FLOW_OK)
- return res;
- else if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), buf))
- return GST_FLOW_ERROR;
-
- wav->offset += 12;
-
- return GST_FLOW_OK;
-}
-
/* This function is used to perform seeks on the element in
* pull mode.
*
gboolean update;
GstSegment seeksegment;
+
if (event) {
GST_DEBUG_OBJECT (wav, "doing seek with event");
flush = flags & GST_SEEK_FLAG_FLUSH;
- if (flush && wav->srcpad) {
- GST_DEBUG_OBJECT (wav, "sending flush start");
+ if (flush)
gst_pad_push_event (wav->srcpad, gst_event_new_flush_start ());
- } else {
+ else
gst_pad_pause_task (wav->sinkpad);
- }
GST_PAD_STREAM_LOCK (wav->sinkpad);
GST_TIME_ARGS (seeksegment.start), GST_TIME_ARGS (stop));
/* prepare for streaming again */
- if (wav->srcpad) {
- if (flush) {
- GST_DEBUG_OBJECT (wav, "sending flush stop");
- gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop ());
- } else if (wav->segment_running) {
- /* we are running the current segment and doing a non-flushing seek,
- * close the segment first based on the last_stop. */
- GST_DEBUG_OBJECT (wav, "closing running segment %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, wav->segment.start, wav->segment.last_stop);
-
- gst_pad_push_event (wav->srcpad,
- gst_event_new_new_segment (TRUE,
- wav->segment.rate, wav->segment.format,
- wav->segment.start, wav->segment.last_stop, wav->segment.time));
- }
+ if (flush) {
+ gst_pad_push_event (wav->srcpad, gst_event_new_flush_stop ());
+ } else if (wav->segment_running) {
+ /* we are running the current segment and doing a non-flushing seek,
+ * close the segment first based on the last_stop. */
+ GST_DEBUG_OBJECT (wav, "closing running segment %" G_GINT64_FORMAT
+ " to %" G_GINT64_FORMAT, wav->segment.start, wav->segment.last_stop);
+
+ gst_pad_push_event (wav->srcpad,
+ gst_event_new_new_segment (TRUE,
+ wav->segment.rate, wav->segment.format,
+ wav->segment.start, wav->segment.last_stop, wav->segment.time));
}
memcpy (&wav->segment, &seeksegment, sizeof (GstSegment));
}
}
-
-/*
- * gst_wavparse_peek_chunk_info:
- * @wav Wavparse object
- * @tag holder for tag
- * @size holder for tag size
- *
- * Peek next chunk info (tag and size)
- *
- * Returns: %TRUE when one chunk info has been got from the adapter
- */
-static gboolean
-gst_wavparse_peek_chunk_info (GstWavParse * wav, guint32 * tag, guint32 * size)
-{
- const guint8 *data = NULL;
-
- if (gst_adapter_available (wav->adapter) < 8) {
- return FALSE;
- }
-
- GST_DEBUG ("Next chunk size is %d bytes", *size);
- data = gst_adapter_peek (wav->adapter, 8);
- *tag = GST_READ_UINT32_LE (data);
- *size = GST_READ_UINT32_LE (data + 4);
-
- return TRUE;
-}
-
-
-/*
- * gst_wavparse_peek_chunk:
- * @wav Wavparse object
- * @tag holder for tag
- * @size holder for tag size
- *
- * Peek enough data for one full chunk
- *
- * Returns: %TRUE when one chunk has been got
- */
-static gboolean
-gst_wavparse_peek_chunk (GstWavParse * wav, guint32 * tag, guint32 * size)
-{
- guint32 peek_size = 0;
-
- gst_wavparse_peek_chunk_info (wav, tag, size);
- GST_DEBUG ("Need to peek chunk of %d bytes", *size);
- peek_size = (*size + 1) & ~1;
-
- if (gst_adapter_available (wav->adapter) >= (8 + peek_size)) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
static gboolean
gst_wavparse_get_upstream_size (GstWavParse * wav, gint64 * len)
{
gst_wavparse_stream_headers (GstWavParse * wav)
{
GstFlowReturn res;
- GstBuffer *buf;
+ GstBuffer *buf, *extra;
gst_riff_strf_auds *header = NULL;
- guint32 tag, size;
+ guint32 tag;
gboolean gotdata = FALSE;
GstCaps *caps;
gint64 duration;
gchar *codec_name = NULL;
GstEvent **event_p;
- if (!wav->got_fmt) {
- GstBuffer *extra;
-
- /* The header start with a 'fmt ' tag */
-
- if (wav->streaming) {
- if (!gst_wavparse_peek_chunk (wav, &tag, &size))
- return GST_FLOW_OK;
-
- buf = gst_buffer_new ();
- gst_buffer_ref (buf);
- gst_adapter_flush (wav->adapter, 8);
- wav->offset += 8;
- GST_BUFFER_DATA (buf) = (guint8 *) gst_adapter_peek (wav->adapter, size);
- GST_BUFFER_SIZE (buf) = size;
-
- } else {
- if ((res = gst_riff_read_chunk (GST_ELEMENT (wav), wav->sinkpad,
- &wav->offset, &tag, &buf)) != GST_FLOW_OK)
- return res;
- }
-
- if (tag != GST_RIFF_TAG_fmt)
- goto invalid_wav;
-
- if (!(gst_riff_parse_strf_auds (GST_ELEMENT (wav), buf, &header, &extra)))
- goto parse_header_error;
-
- if (extra)
- gst_buffer_unref (extra);
+ /* The header start with a 'fmt ' tag */
+ if ((res = gst_riff_read_chunk (GST_ELEMENT (wav), wav->sinkpad,
+ &wav->offset, &tag, &buf)) != GST_FLOW_OK)
+ return res;
- if (wav->streaming) {
- gst_adapter_flush (wav->adapter, size);
- wav->offset += size;
- GST_BUFFER_DATA (buf) = NULL;
- gst_buffer_unref (buf);
- }
+ else if (tag != GST_RIFF_TAG_fmt)
+ goto invalid_wav;
- /* Note: gst_riff_create_audio_caps might nedd to fix values in
- * the header header depending on the format, so call it first */
- caps =
- gst_riff_create_audio_caps (header->format, NULL, header, NULL,
- NULL, &codec_name);
+ if (!(gst_riff_parse_strf_auds (GST_ELEMENT (wav), buf, &header, &extra)))
+ goto parse_header_error;
- wav->format = header->format;
- wav->rate = header->rate;
- wav->channels = header->channels;
+ /* Note: gst_riff_create_audio_caps might nedd to fix values in
+ * the header header depending on the format, so call it first */
+ caps =
+ gst_riff_create_audio_caps (header->format, NULL, header, extra,
+ NULL, &codec_name);
- if (wav->channels == 0)
- goto no_channels;
+ if (extra)
+ gst_buffer_unref (extra);
- wav->blockalign = header->blockalign;
- wav->width = (header->blockalign * 8) / header->channels;
- wav->depth = header->size;
- wav->bps = header->av_bps;
+ wav->format = header->format;
+ wav->rate = header->rate;
+ wav->channels = header->channels;
- if (wav->bps <= 0)
- goto no_bitrate;
+ if (wav->channels == 0)
+ goto no_channels;
- wav->bytes_per_sample = wav->channels * wav->width / 8;
- if (wav->bytes_per_sample <= 0)
- goto no_bytes_per_sample;
+ wav->blockalign = header->blockalign;
+ wav->width = (header->blockalign * 8) / header->channels;
+ wav->depth = header->size;
+ wav->bps = header->av_bps;
- g_free (header);
+ if (wav->bps <= 0)
+ goto no_bitrate;
- if (!caps)
- goto unknown_format;
+ wav->bytes_per_sample = wav->channels * wav->width / 8;
+ if (wav->bytes_per_sample <= 0)
+ goto no_bytes_per_sample;
- GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
- GST_DEBUG_OBJECT (wav, "width = %u", (guint) wav->width);
- GST_DEBUG_OBJECT (wav, "depth = %u", (guint) wav->depth);
- GST_DEBUG_OBJECT (wav, "bps = %u", (guint) wav->bps);
+ g_free (header);
- /* create pad later so we can sniff the first few bytes
- * of the real data and correct our caps if necessary */
- gst_caps_replace (&wav->caps, caps);
- gst_caps_replace (&caps, NULL);
+ if (!caps)
+ goto unknown_format;
- wav->got_fmt = TRUE;
+ GST_DEBUG_OBJECT (wav, "blockalign = %u", (guint) wav->blockalign);
+ GST_DEBUG_OBJECT (wav, "width = %u", (guint) wav->width);
+ GST_DEBUG_OBJECT (wav, "depth = %u", (guint) wav->depth);
+ GST_DEBUG_OBJECT (wav, "bps = %u", (guint) wav->bps);
- if (codec_name) {
- wav->tags = gst_tag_list_new ();
+ /* create pad later so we can sniff the first few bytes
+ * of the real data and correct our caps if necessary */
+ gst_caps_replace (&wav->caps, caps);
+ gst_caps_replace (&caps, NULL);
- gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_AUDIO_CODEC, codec_name, NULL);
+ if (codec_name) {
+ wav->tags = gst_tag_list_new ();
- g_free (codec_name);
- codec_name = NULL;
- }
+ gst_tag_list_add (wav->tags, GST_TAG_MERGE_REPLACE,
+ GST_TAG_AUDIO_CODEC, codec_name, NULL);
- GST_DEBUG_OBJECT (wav, "frequency %d, channels %d", wav->rate,
- wav->channels);
+ g_free (codec_name);
+ codec_name = NULL;
}
+ GST_DEBUG_OBJECT (wav, "frequency %d, channels %d", wav->rate, wav->channels);
+
/* loop headers until we get data */
while (!gotdata) {
- if (wav->streaming) {
- if (!gst_wavparse_peek_chunk_info (wav, &tag, &size))
- return GST_FLOW_OK;
- } else {
- if ((res =
- gst_pad_pull_range (wav->sinkpad, wav->offset, 8,
- &buf)) != GST_FLOW_OK)
- goto header_read_error;
- tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
- size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
- }
+ guint size;
+ guint32 tag;
+
+ if ((res =
+ gst_pad_pull_range (wav->sinkpad, wav->offset, 8,
+ &buf)) != GST_FLOW_OK)
+ goto header_read_error;
/*
wav is a st00pid format, we don't know for sure where data starts.
So we have to go bit by bit until we find the 'data' header
*/
+ tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf));
+ size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4);
switch (tag) {
/* TODO : Implement the various cases */
GST_DEBUG_OBJECT (wav, "Got 'data' TAG, size : %d", size);
gotdata = TRUE;
- if (wav->streaming) {
- gst_adapter_flush (wav->adapter, 8);
- } else {
- gst_buffer_unref (buf);
- }
wav->offset += 8;
wav->datastart = wav->offset;
/* file might be truncated */
break;
}
default:
- if (wav->streaming) {
- if (!gst_wavparse_peek_chunk (wav, &tag, &size))
- return GST_FLOW_OK;
- }
GST_DEBUG_OBJECT (wav, "Ignoring tag %" GST_FOURCC_FORMAT,
GST_FOURCC_ARGS (tag));
wav->offset += 8 + ((size + 1) & ~1);
- if (wav->streaming) {
- gst_adapter_flush (wav->adapter, 8 + ((size + 1) & ~1));
- } else {
- gst_buffer_unref (buf);
- }
+ break;
}
+ gst_buffer_unref (buf);
}
GST_DEBUG_OBJECT (wav, "Finished parsing headers");
event_p = &wav->seek_event;
gst_event_replace (event_p, NULL);
- wav->state = GST_WAVPARSE_DATA;
return GST_FLOW_OK;
/* ERROR */
}
}
-
-/*
- * Read WAV file tag when streaming
- */
-static GstFlowReturn
-gst_wavparse_parse_stream_init (GstWavParse * wav)
-{
- if (gst_adapter_available (wav->adapter) >= 12) {
- GstBuffer *tmp = gst_buffer_new ();
-
- /* _take flushes the data */
- GST_BUFFER_DATA (tmp) = gst_adapter_take (wav->adapter, 12);
- GST_BUFFER_SIZE (tmp) = 12;
-
- GST_DEBUG ("Parsing wav header");
- if (!gst_wavparse_parse_file_header (GST_ELEMENT (wav), tmp)) {
- return GST_FLOW_ERROR;
- }
-
- wav->offset += 12;
- /* Go to next state */
- wav->state = GST_WAVPARSE_HEADER;
- }
- return GST_FLOW_OK;
-}
-
/* handle an event sent directly to the element.
*
* This event can be sent either in the READY state or the
gboolean res = FALSE;
GstEvent **event_p;
- GST_DEBUG_OBJECT (wav, "received event %s", GST_EVENT_TYPE_NAME (event));
-
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_SEEK:
if (wav->state == GST_WAVPARSE_DATA) {
gst_element_add_pad (GST_ELEMENT (wav), wav->srcpad);
gst_element_no_more_pads (GST_ELEMENT (wav));
- GST_DEBUG_OBJECT (wav, "Send newsegment event on newpad");
gst_pad_push_event (wav->srcpad, wav->newsegment);
wav->newsegment = NULL;
#define MAX_BUFFER_SIZE 4096
static GstFlowReturn
-gst_wavparse_stream_data (GstWavParse * wav)
+gst_wavparse_stream_data (GstWavParse * wav, gboolean first)
{
GstBuffer *buf = NULL;
GstFlowReturn res = GST_FLOW_OK;
GstClockTime timestamp, next_timestamp;
guint64 pos, nextpos;
-iterate_adapter:
- GST_LOG_OBJECT (wav,
- "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT " , dataleft: %"
- G_GINT64_FORMAT, wav->offset, wav->end_offset, wav->dataleft);
+ GST_LOG_OBJECT (wav, "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT,
+ wav->offset, wav->end_offset);
/* Get the next n bytes and output them */
if (wav->dataleft == 0 || wav->dataleft < wav->blockalign)
GST_LOG_OBJECT (wav, "Fetching %" G_GINT64_FORMAT " bytes of data "
"from the sinkpad", desired);
- if (wav->streaming) {
- guint avail = gst_adapter_available (wav->adapter);
-
- if (avail < desired) {
- GST_LOG_OBJECT (wav, "Got only %d bytes of data from the sinkpad", avail);
- return GST_FLOW_OK;
- }
+ if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
+ desired, &buf)) != GST_FLOW_OK)
+ goto pull_error;
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = gst_adapter_take (wav->adapter, desired);
- GST_BUFFER_SIZE (buf) = desired;
- } else {
- if ((res = gst_pad_pull_range (wav->sinkpad, wav->offset,
- desired, &buf)) != GST_FLOW_OK)
- goto pull_error;
- }
+ obtained = GST_BUFFER_SIZE (buf);
/* first chunk of data? create the source pad. We do this only here so
* we can detect broken .wav files with dts disguised as raw PCM (sigh) */
- if (G_UNLIKELY (wav->first)) {
- wav->first = FALSE;
+ if (first) {
gst_wavparse_add_src_pad (wav, buf);
}
- obtained = GST_BUFFER_SIZE (buf);
-
/* our positions */
pos = wav->offset - wav->datastart;
nextpos = pos + obtained;
", size:%u", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf));
- if (gst_pad_is_linked (wav->srcpad)) {
- if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
- goto push_error;
- } else {
- gst_buffer_unref (buf);
- goto not_linked;
- }
+ if ((res = gst_pad_push (wav->srcpad, buf)) != GST_FLOW_OK)
+ goto push_error;
if (obtained < wav->dataleft) {
wav->dataleft -= obtained;
- //wav->offset += obtained;
+ wav->offset += obtained;
} else {
wav->dataleft = 0;
}
- wav->offset += obtained;
- /* Iterate until need more data, so adapter size won't grow */
- if (wav->streaming) {
- GST_LOG_OBJECT (wav,
- "offset: %" G_GINT64_FORMAT " , end: %" G_GINT64_FORMAT, wav->offset,
- wav->end_offset);
- goto iterate_adapter;
- }
-
return res;
/* ERROR */
GST_DEBUG_OBJECT (wav, "Error pushing on srcpad");
return res;
}
-not_linked:
- {
- GST_DEBUG_OBJECT (wav, "Srcpad not linked!");
- return GST_FLOW_ERROR;
- }
}
static void
GstFlowReturn ret;
GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
- GST_LOG_OBJECT (wav, "process data");
-
switch (wav->state) {
case GST_WAVPARSE_START:
- GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
if ((ret = gst_wavparse_stream_init (wav)) != GST_FLOW_OK)
goto pause;
/* fall-through */
case GST_WAVPARSE_HEADER:
- GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
goto pause;
wav->state = GST_WAVPARSE_DATA;
- /* fall-through */
-
- case GST_WAVPARSE_DATA:
- if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
+ if ((ret = gst_wavparse_stream_data (wav, TRUE)) != GST_FLOW_OK)
goto pause;
break;
- default:
- g_assert_not_reached ();
- }
-
- return;
-
- /* ERRORS */
-pause:
- GST_LOG_OBJECT (wav, "pausing task %d", ret);
- gst_pad_pause_task (wav->sinkpad);
- if (GST_FLOW_IS_FATAL (ret)) {
- /* for fatal errors we post an error message */
- GST_ELEMENT_ERROR (wav, STREAM, FAILED,
- (_("Internal data stream error.")),
- ("streaming stopped, reason %s", gst_flow_get_name (ret)));
- if (wav->srcpad != NULL)
- gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
- }
-}
-
-static GstFlowReturn
-gst_wavparse_chain (GstPad * pad, GstBuffer * buf)
-{
- GstFlowReturn ret;
- GstWavParse *wav = GST_WAVPARSE (GST_PAD_PARENT (pad));
-
- GST_LOG_OBJECT (wav, "adapter_push %" G_GINT64_FORMAT " bytes",
- GST_BUFFER_SIZE (buf));
-
- gst_adapter_push (wav->adapter, buf);
-
- switch (wav->state) {
- case GST_WAVPARSE_START:
- GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_START");
- if ((ret = gst_wavparse_parse_stream_init (wav)) != GST_FLOW_OK)
- goto pause;
-
- wav->state = GST_WAVPARSE_HEADER;
- /* fall-through */
-
- case GST_WAVPARSE_HEADER:
- GST_DEBUG_OBJECT (wav, "GST_WAVPARSE_HEADER");
- if ((ret = gst_wavparse_stream_headers (wav)) != GST_FLOW_OK)
- goto pause;
-
- wav->state = GST_WAVPARSE_DATA;
- /* fall-through */
-
case GST_WAVPARSE_DATA:
- if ((ret = gst_wavparse_stream_data (wav)) != GST_FLOW_OK)
+ if ((ret = gst_wavparse_stream_data (wav, FALSE)) != GST_FLOW_OK)
goto pause;
break;
default:
g_assert_not_reached ();
}
- return ret;
+ return;
+ /* ERRORS */
pause:
GST_LOG_OBJECT (wav, "pausing task %d", ret);
gst_pad_pause_task (wav->sinkpad);
if (wav->srcpad != NULL)
gst_pad_push_event (wav->srcpad, gst_event_new_eos ());
}
- return ret;
}
#if 0
GstWavParse *wavparse = GST_WAVPARSE (GST_PAD_PARENT (pad));
gboolean res = TRUE;
- GST_DEBUG_OBJECT (wavparse, "event %d, %s", GST_EVENT_TYPE (event),
- GST_EVENT_TYPE_NAME (event));
+ GST_DEBUG_OBJECT (wavparse, "event %d", GST_EVENT_TYPE (event));
/* can only handle events when we are in the data state */
if (wavparse->state != GST_WAVPARSE_DATA)
static gboolean
gst_wavparse_sink_activate (GstPad * sinkpad)
{
- GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
-
- if (gst_pad_check_pull_range (sinkpad)) {
- GST_DEBUG ("going to pull mode");
- wav->streaming = FALSE;
- wav->adapter = NULL;
- gst_object_unref (wav);
+ if (gst_pad_check_pull_range (sinkpad))
return gst_pad_activate_pull (sinkpad, TRUE);
- } else {
- GST_DEBUG ("going to push (streaming) mode");
- wav->streaming = TRUE;
- wav->adapter = gst_adapter_new ();
- gst_object_unref (wav);
- return gst_pad_activate_push (sinkpad, TRUE);
- }
-}
+ /* FIXME, we can only operate in pull mode for now */
+ GST_DEBUG_OBJECT (sinkpad, "pull_range not supported on sinkpad");
+ return FALSE;
+};
static gboolean
gst_wavparse_sink_activate_pull (GstPad * sinkpad, gboolean active)
{
GstWavParse *wav = GST_WAVPARSE (gst_pad_get_parent (sinkpad));
- GST_DEBUG_OBJECT (wav, "activating pull");
-
if (active) {
- /* if we have a scheduler we can start the task */
- wav->segment_running = TRUE;
gst_pad_start_task (sinkpad, (GstTaskFunction) gst_wavparse_loop, sinkpad);
} else {
gst_pad_stop_task (sinkpad);
GstStateChangeReturn ret;
GstWavParse *wav = GST_WAVPARSE (element);
- GST_DEBUG_OBJECT (wav, "chaning state");
-
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
break;
gst_wavparse_destroy_sourcepad (wav);
gst_event_replace (event_p, NULL);
gst_wavparse_reset (wav);
- if (wav->adapter) {
- gst_adapter_clear (wav->adapter);
- }
- break;
}
+ break;
case GST_STATE_CHANGE_READY_TO_NULL:
break;
default:
{
gst_riff_init ();
- GST_DEBUG_CATEGORY_INIT (wavparse_debug, "wavparse", 0, "WAV parser");
-
return gst_element_register (plugin, "wavparse", GST_RANK_PRIMARY,
GST_TYPE_WAVPARSE);
}