Commit 422c6fcc authored by Stefan Kost's avatar Stefan Kost
Browse files

gst/wavparse/gstwavparse.*: reverted patch #337625 for the price of 1 hour sleep

Original commit message from CVS:
* gst/wavparse/gstwavparse.c: (gst_wavparse_base_init),
(gst_wavparse_class_init), (gst_wavparse_reset),
(gst_wavparse_init), (gst_wavparse_create_sourcepad),
(gst_wavparse_parse_file_header), (gst_wavparse_stream_init),
(gst_wavparse_perform_seek), (gst_wavparse_stream_headers),
(gst_wavparse_send_event), (gst_wavparse_add_src_pad),
(gst_wavparse_stream_data), (gst_wavparse_loop),
(gst_wavparse_srcpad_event), (gst_wavparse_sink_activate),
(gst_wavparse_sink_activate_pull), (gst_wavparse_change_state),
(plugin_init):
* gst/wavparse/gstwavparse.h:
reverted patch #337625 for the price of 1 hour sleep
parent 562de2f6
2006-04-27 Stefan Kost <ensonic@users.sf.net>
* gst/wavparse/gstwavparse.c: (gst_wavparse_base_init),
(gst_wavparse_class_init), (gst_wavparse_reset),
(gst_wavparse_init), (gst_wavparse_create_sourcepad),
(gst_wavparse_parse_file_header), (gst_wavparse_stream_init),
(gst_wavparse_perform_seek), (gst_wavparse_stream_headers),
(gst_wavparse_send_event), (gst_wavparse_add_src_pad),
(gst_wavparse_stream_data), (gst_wavparse_loop),
(gst_wavparse_srcpad_event), (gst_wavparse_sink_activate),
(gst_wavparse_sink_activate_pull), (gst_wavparse_change_state),
(plugin_init):
* gst/wavparse/gstwavparse.h:
reverted patch #337625 for the price of 1 hour sleep
2006-04-26 Stefan Kost <ensonic@users.sf.net>
* gst/wavparse/gstwavparse.c: (gst_wavparse_base_init),
......
/* -*- 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
......@@ -32,18 +31,11 @@
* <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)
......@@ -59,24 +51,18 @@
#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);
......@@ -91,12 +77,6 @@ static gboolean gst_wavparse_srcpad_event (GstPad * pad, GstEvent * event);
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,
......@@ -175,13 +155,22 @@ static void
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
......@@ -196,28 +185,13 @@ gst_wavparse_class_init (GstWavParseClass * klass)
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)
{
......@@ -235,12 +209,6 @@ 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);
......@@ -258,12 +226,7 @@ gst_wavparse_init (GstWavParse * wavparse)
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
......@@ -291,8 +254,6 @@ gst_wavparse_create_sourcepad (GstWavParse * wavparse)
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
......@@ -309,8 +270,6 @@ gst_wavparse_get_property (GObject * object,
}
}
#if 0
static void
gst_wavparse_parse_adtl (GstWavParse * wavparse, int len)
......@@ -494,7 +453,9 @@ 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)
{
......@@ -557,7 +518,49 @@ 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)
......@@ -715,48 +718,6 @@ gst_wavparse_other (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.
*
......@@ -779,6 +740,7 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)
gboolean update;
GstSegment seeksegment;
if (event) {
GST_DEBUG_OBJECT (wav, "doing seek with event");
......@@ -808,12 +770,10 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * 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);
......@@ -854,21 +814,18 @@ gst_wavparse_perform_seek (GstWavParse * wav, GstEvent * event)
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));
......@@ -911,61 +868,6 @@ no_format:
}
}
/*
* 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)
{
......@@ -985,127 +887,97 @@ static GstFlowReturn
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 */
......@@ -1114,11 +986,6 @@ gst_wavparse_stream_headers (GstWavParse * wav)
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 */
......@@ -1131,19 +998,12 @@ gst_wavparse_stream_headers (GstWavParse * wav)
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;