2001-12-23 14:15:30 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
|
2011-09-28 17:32:00 +00:00
|
|
|
* Copyright (C) <2006,2011> Tim-Philipp Müller <tim centricular net>
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
* Copyright (C) <2006> Jan Schmidt <thaytan at mad scientist com>
|
2001-12-23 14:15:30 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
2012-11-04 00:07:18 +00:00
|
|
|
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
2001-12-23 14:15:30 +00:00
|
|
|
*/
|
|
|
|
|
2005-11-25 22:14:47 +00:00
|
|
|
/**
|
|
|
|
* SECTION:element-flacdec
|
2009-01-28 15:46:06 +00:00
|
|
|
* @see_also: #GstFlacEnc
|
2005-11-25 22:14:47 +00:00
|
|
|
*
|
|
|
|
* flacdec decodes FLAC streams.
|
|
|
|
* <ulink url="http://flac.sourceforge.net/">FLAC</ulink>
|
|
|
|
* is a Free Lossless Audio Codec.
|
2009-01-28 15:46:06 +00:00
|
|
|
*
|
|
|
|
* <refsect2>
|
2005-11-25 22:14:47 +00:00
|
|
|
* <title>Example launch line</title>
|
2009-01-28 15:46:06 +00:00
|
|
|
* |[
|
2012-08-26 21:32:54 +00:00
|
|
|
* gst-launch-1.0 filesrc location=media/small/dark.441-16-s.flac ! flacparse ! flacdec ! audioconvert ! audioresample ! autoaudiosink
|
2009-01-28 15:46:06 +00:00
|
|
|
* ]|
|
|
|
|
* |[
|
2012-08-26 21:32:54 +00:00
|
|
|
* gst-launch-1.0 souphttpsrc location=http://gstreamer.freedesktop.org/media/small/dark.441-16-s.flac ! flacparse ! flacdec ! audioconvert ! audioresample ! queue min-threshold-buffers=10 ! autoaudiosink
|
2009-01-28 15:46:06 +00:00
|
|
|
* ]|
|
2005-11-25 22:14:47 +00:00
|
|
|
* </refsect2>
|
|
|
|
*/
|
|
|
|
|
2003-06-29 19:46:12 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
2011-12-12 02:52:13 +00:00
|
|
|
|
2001-12-23 14:15:30 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "gstflacdec.h"
|
2007-05-02 17:08:09 +00:00
|
|
|
#include <gst/gst-i18n-plugin.h>
|
2005-10-02 15:33:14 +00:00
|
|
|
#include <gst/tag/tag.h>
|
2001-12-23 14:15:30 +00:00
|
|
|
|
2008-05-25 16:09:39 +00:00
|
|
|
/* Taken from http://flac.sourceforge.net/format.html#frame_header */
|
|
|
|
static const GstAudioChannelPosition channel_positions[8][8] = {
|
2012-01-06 08:40:22 +00:00
|
|
|
{GST_AUDIO_CHANNEL_POSITION_MONO},
|
2008-05-25 16:09:39 +00:00
|
|
|
{GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, {
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, {
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, {
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
2012-01-06 08:40:22 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
2008-05-25 16:09:39 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT},
|
|
|
|
/* FIXME: 7/8 channel layouts are not defined in the FLAC specs */
|
|
|
|
{
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
2012-01-06 08:40:22 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
2008-05-25 16:09:39 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, {
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER,
|
2012-01-06 08:40:22 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_LFE1,
|
2008-05-25 16:09:39 +00:00
|
|
|
GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT,
|
|
|
|
GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}
|
|
|
|
};
|
|
|
|
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
GST_DEBUG_CATEGORY_STATIC (flacdec_debug);
|
|
|
|
#define GST_CAT_DEFAULT flacdec_debug
|
|
|
|
|
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
Original commit message from CVS:
Patch by: Josh Coalson <xflac at yahoo dot com>,
updated by Alexis Ballier <aballier at gentoo dot org>:
* configure.ac:
* ext/flac/gstflacdec.c: (gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_seek),
(gst_flac_dec_tell), (gst_flac_dec_length), (gst_flac_dec_eof),
(gst_flac_dec_read_seekable), (gst_flac_dec_read_stream):
* ext/flac/gstflacdec.h:
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_finalize), (gst_flac_enc_set_metadata),
(gst_flac_enc_sink_setcaps), (gst_flac_enc_update_quality),
(gst_flac_enc_seek_callback), (gst_flac_enc_write_callback),
(gst_flac_enc_tell_callback), (gst_flac_enc_sink_event),
(gst_flac_enc_chain), (gst_flac_enc_set_property),
(gst_flac_enc_get_property), (gst_flac_enc_change_state):
* ext/flac/gstflacenc.h:
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
2007-06-10 10:53:26 +00:00
|
|
|
static FLAC__StreamDecoderReadStatus
|
|
|
|
gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
|
|
|
|
FLAC__byte buffer[], size_t * bytes, void *client_data);
|
|
|
|
static FLAC__StreamDecoderWriteStatus
|
|
|
|
gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
|
|
|
|
const FLAC__Frame * frame,
|
|
|
|
const FLAC__int32 * const buffer[], void *client_data);
|
2015-06-26 04:24:17 +00:00
|
|
|
static gboolean
|
|
|
|
gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg);
|
2009-08-01 15:48:36 +00:00
|
|
|
static void gst_flac_dec_metadata_cb (const FLAC__StreamDecoder *
|
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
Original commit message from CVS:
Patch by: Josh Coalson <xflac at yahoo dot com>,
updated by Alexis Ballier <aballier at gentoo dot org>:
* configure.ac:
* ext/flac/gstflacdec.c: (gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_seek),
(gst_flac_dec_tell), (gst_flac_dec_length), (gst_flac_dec_eof),
(gst_flac_dec_read_seekable), (gst_flac_dec_read_stream):
* ext/flac/gstflacdec.h:
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_finalize), (gst_flac_enc_set_metadata),
(gst_flac_enc_sink_setcaps), (gst_flac_enc_update_quality),
(gst_flac_enc_seek_callback), (gst_flac_enc_write_callback),
(gst_flac_enc_tell_callback), (gst_flac_enc_sink_event),
(gst_flac_enc_chain), (gst_flac_enc_set_property),
(gst_flac_enc_get_property), (gst_flac_enc_change_state):
* ext/flac/gstflacenc.h:
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
2007-06-10 10:53:26 +00:00
|
|
|
decoder, const FLAC__StreamMetadata * metadata, void *client_data);
|
2009-08-01 15:48:36 +00:00
|
|
|
static void gst_flac_dec_error_cb (const FLAC__StreamDecoder *
|
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
Original commit message from CVS:
Patch by: Josh Coalson <xflac at yahoo dot com>,
updated by Alexis Ballier <aballier at gentoo dot org>:
* configure.ac:
* ext/flac/gstflacdec.c: (gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_seek),
(gst_flac_dec_tell), (gst_flac_dec_length), (gst_flac_dec_eof),
(gst_flac_dec_read_seekable), (gst_flac_dec_read_stream):
* ext/flac/gstflacdec.h:
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_finalize), (gst_flac_enc_set_metadata),
(gst_flac_enc_sink_setcaps), (gst_flac_enc_update_quality),
(gst_flac_enc_seek_callback), (gst_flac_enc_write_callback),
(gst_flac_enc_tell_callback), (gst_flac_enc_sink_event),
(gst_flac_enc_chain), (gst_flac_enc_set_property),
(gst_flac_enc_get_property), (gst_flac_enc_change_state):
* ext/flac/gstflacenc.h:
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
2007-06-10 10:53:26 +00:00
|
|
|
decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
2001-12-23 14:15:30 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
static void gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard);
|
|
|
|
static gboolean gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps);
|
|
|
|
static gboolean gst_flac_dec_start (GstAudioDecoder * dec);
|
|
|
|
static gboolean gst_flac_dec_stop (GstAudioDecoder * dec);
|
|
|
|
static GstFlowReturn gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec,
|
|
|
|
GstBuffer * buf);
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (GstFlacDec, gst_flac_dec, GST_TYPE_AUDIO_DECODER);
|
2008-08-07 14:40:13 +00:00
|
|
|
|
2011-09-28 15:40:01 +00:00
|
|
|
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
2014-02-04 12:43:56 +00:00
|
|
|
#define FORMATS "{ S8, S16LE, S24_32LE, S32LE } "
|
2011-09-28 15:40:01 +00:00
|
|
|
#else
|
2014-02-04 12:43:56 +00:00
|
|
|
#define FORMATS "{ S8, S16BE, S24_32BE, S32BE } "
|
2011-09-28 15:40:01 +00:00
|
|
|
#endif
|
|
|
|
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
#define GST_FLAC_DEC_SRC_CAPS \
|
2011-09-28 15:40:01 +00:00
|
|
|
"audio/x-raw, " \
|
|
|
|
"format = (string) " FORMATS ", " \
|
2012-01-06 08:40:22 +00:00
|
|
|
"layout = (string) interleaved, " \
|
2008-08-03 11:38:22 +00:00
|
|
|
"rate = (int) [ 1, 655350 ], " \
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
"channels = (int) [ 1, 8 ]"
|
2008-12-13 15:34:01 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
#define GST_FLAC_DEC_SINK_CAPS \
|
|
|
|
"audio/x-flac, " \
|
|
|
|
"framed = (boolean) true, " \
|
|
|
|
"rate = (int) [ 1, 655350 ], " \
|
|
|
|
"channels = (int) [ 1, 8 ]"
|
|
|
|
|
2008-12-13 15:34:01 +00:00
|
|
|
static GstStaticPadTemplate flac_dec_src_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE ("src",
|
|
|
|
GST_PAD_SRC,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS (GST_FLAC_DEC_SRC_CAPS));
|
|
|
|
static GstStaticPadTemplate flac_dec_sink_factory =
|
|
|
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
2011-10-09 15:18:09 +00:00
|
|
|
GST_STATIC_CAPS (GST_FLAC_DEC_SINK_CAPS));
|
2008-12-13 15:34:01 +00:00
|
|
|
|
2001-12-23 14:15:30 +00:00
|
|
|
static void
|
2005-12-09 19:51:03 +00:00
|
|
|
gst_flac_dec_class_init (GstFlacDecClass * klass)
|
2001-12-23 14:15:30 +00:00
|
|
|
{
|
2011-10-09 15:18:09 +00:00
|
|
|
GstAudioDecoderClass *audiodecoder_class;
|
2001-12-23 14:15:30 +00:00
|
|
|
GstElementClass *gstelement_class;
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
audiodecoder_class = (GstAudioDecoderClass *) klass;
|
2004-03-14 22:34:33 +00:00
|
|
|
gstelement_class = (GstElementClass *) klass;
|
2001-12-23 14:15:30 +00:00
|
|
|
|
2011-04-19 16:55:31 +00:00
|
|
|
GST_DEBUG_CATEGORY_INIT (flacdec_debug, "flacdec", 0, "flac decoder");
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
audiodecoder_class->stop = GST_DEBUG_FUNCPTR (gst_flac_dec_stop);
|
|
|
|
audiodecoder_class->start = GST_DEBUG_FUNCPTR (gst_flac_dec_start);
|
|
|
|
audiodecoder_class->flush = GST_DEBUG_FUNCPTR (gst_flac_dec_flush);
|
|
|
|
audiodecoder_class->set_format = GST_DEBUG_FUNCPTR (gst_flac_dec_set_format);
|
|
|
|
audiodecoder_class->handle_frame =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_flac_dec_handle_frame);
|
2011-04-19 16:55:31 +00:00
|
|
|
|
|
|
|
gst_element_class_add_pad_template (gstelement_class,
|
|
|
|
gst_static_pad_template_get (&flac_dec_src_factory));
|
|
|
|
gst_element_class_add_pad_template (gstelement_class,
|
|
|
|
gst_static_pad_template_get (&flac_dec_sink_factory));
|
|
|
|
|
2012-04-09 23:51:41 +00:00
|
|
|
gst_element_class_set_static_metadata (gstelement_class, "FLAC audio decoder",
|
2011-10-09 15:18:09 +00:00
|
|
|
"Codec/Decoder/Audio", "Decodes FLAC lossless audio streams",
|
|
|
|
"Tim-Philipp Müller <tim@centricular.net>, "
|
|
|
|
"Wim Taymans <wim.taymans@gmail.com>");
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
static void
|
2011-04-19 16:55:31 +00:00
|
|
|
gst_flac_dec_init (GstFlacDec * flacdec)
|
2001-12-23 14:15:30 +00:00
|
|
|
{
|
2013-12-05 11:13:10 +00:00
|
|
|
gst_audio_decoder_set_needs_format (GST_AUDIO_DECODER (flacdec), TRUE);
|
2015-08-15 12:16:23 +00:00
|
|
|
gst_audio_decoder_set_use_default_pad_acceptcaps (GST_AUDIO_DECODER_CAST
|
|
|
|
(flacdec), TRUE);
|
|
|
|
GST_PAD_SET_ACCEPT_TEMPLATE (GST_AUDIO_DECODER_SINK_PAD (flacdec));
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
}
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
static gboolean
|
|
|
|
gst_flac_dec_start (GstAudioDecoder * audio_dec)
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
{
|
2011-10-09 15:18:09 +00:00
|
|
|
FLAC__StreamDecoderInitStatus s;
|
|
|
|
GstFlacDec *dec;
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
dec = GST_FLAC_DEC (audio_dec);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
|
|
|
|
dec->adapter = gst_adapter_new ();
|
|
|
|
|
2009-12-23 16:50:34 +00:00
|
|
|
dec->decoder = FLAC__stream_decoder_new ();
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
|
2012-01-06 08:40:22 +00:00
|
|
|
gst_audio_info_init (&dec->info);
|
|
|
|
dec->depth = 0;
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
/* no point calculating MD5 since it's never checked here */
|
2009-12-23 16:50:34 +00:00
|
|
|
FLAC__stream_decoder_set_md5_checking (dec->decoder, false);
|
2011-10-09 15:18:09 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (dec, "initializing decoder");
|
|
|
|
s = FLAC__stream_decoder_init_stream (dec->decoder,
|
|
|
|
gst_flac_dec_read_stream, NULL, NULL, NULL, NULL,
|
|
|
|
gst_flac_dec_write_stream, gst_flac_dec_metadata_cb,
|
|
|
|
gst_flac_dec_error_cb, dec);
|
|
|
|
|
|
|
|
if (s != FLAC__STREAM_DECODER_INIT_STATUS_OK) {
|
|
|
|
GST_ELEMENT_ERROR (GST_ELEMENT (dec), LIBRARY, INIT, (NULL), (NULL));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
dec->got_headers = FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
2002-06-07 20:09:05 +00:00
|
|
|
}
|
2001-12-23 14:15:30 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
static gboolean
|
|
|
|
gst_flac_dec_stop (GstAudioDecoder * dec)
|
2004-05-07 20:26:46 +00:00
|
|
|
{
|
2011-10-09 15:18:09 +00:00
|
|
|
GstFlacDec *flacdec = GST_FLAC_DEC (dec);
|
|
|
|
|
|
|
|
if (flacdec->decoder) {
|
|
|
|
FLAC__stream_decoder_delete (flacdec->decoder);
|
|
|
|
flacdec->decoder = NULL;
|
|
|
|
}
|
2004-05-07 20:26:46 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
if (flacdec->adapter) {
|
|
|
|
gst_adapter_clear (flacdec->adapter);
|
|
|
|
g_object_unref (flacdec->adapter);
|
|
|
|
flacdec->adapter = NULL;
|
|
|
|
}
|
2004-05-07 20:26:46 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
return TRUE;
|
2004-05-07 20:26:46 +00:00
|
|
|
}
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
static gboolean
|
|
|
|
gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps)
|
|
|
|
{
|
2011-10-30 19:09:03 +00:00
|
|
|
const GValue *headers;
|
|
|
|
GstFlacDec *flacdec;
|
|
|
|
GstStructure *s;
|
|
|
|
guint i, num;
|
|
|
|
|
|
|
|
flacdec = GST_FLAC_DEC (dec);
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps);
|
2011-10-30 19:09:03 +00:00
|
|
|
|
|
|
|
s = gst_caps_get_structure (caps, 0);
|
|
|
|
headers = gst_structure_get_value (s, "streamheader");
|
|
|
|
if (headers == NULL || !GST_VALUE_HOLDS_ARRAY (headers)) {
|
|
|
|
GST_WARNING_OBJECT (dec, "no 'streamheader' field in input caps, try "
|
|
|
|
"adding a flacparse element upstream");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gst_adapter_available (flacdec->adapter) > 0) {
|
|
|
|
GST_WARNING_OBJECT (dec, "unexpected data left in adapter");
|
|
|
|
gst_adapter_clear (flacdec->adapter);
|
|
|
|
}
|
|
|
|
|
|
|
|
num = gst_value_array_get_size (headers);
|
|
|
|
for (i = 0; i < num; ++i) {
|
|
|
|
const GValue *header_val;
|
|
|
|
GstBuffer *header_buf;
|
|
|
|
|
|
|
|
header_val = gst_value_array_get_value (headers, i);
|
|
|
|
if (header_val == NULL || !GST_VALUE_HOLDS_BUFFER (header_val))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
header_buf = g_value_dup_boxed (header_val);
|
2011-11-22 01:40:39 +00:00
|
|
|
GST_INFO_OBJECT (dec, "pushing header buffer of %" G_GSIZE_FORMAT " bytes "
|
|
|
|
"into adapter", gst_buffer_get_size (header_buf));
|
2011-10-30 19:09:03 +00:00
|
|
|
gst_adapter_push (flacdec->adapter, header_buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (dec, "Processing headers and metadata");
|
|
|
|
if (!FLAC__stream_decoder_process_until_end_of_metadata (flacdec->decoder)) {
|
|
|
|
GST_WARNING_OBJECT (dec, "process_until_end_of_metadata failed");
|
2015-06-26 04:24:17 +00:00
|
|
|
if (FLAC__stream_decoder_get_state (flacdec->decoder) ==
|
|
|
|
FLAC__STREAM_DECODER_ABORTED) {
|
|
|
|
GST_WARNING_OBJECT (flacdec, "Read callback caused internal abort");
|
|
|
|
/* allow recovery */
|
|
|
|
gst_adapter_clear (flacdec->adapter);
|
|
|
|
FLAC__stream_decoder_flush (flacdec->decoder);
|
|
|
|
gst_flac_dec_handle_decoder_error (flacdec, TRUE);
|
|
|
|
}
|
2011-10-30 19:09:03 +00:00
|
|
|
}
|
|
|
|
GST_INFO_OBJECT (dec, "headers and metadata are now processed");
|
2011-10-09 15:18:09 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
2004-05-07 20:26:46 +00:00
|
|
|
|
2006-04-07 18:15:08 +00:00
|
|
|
/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
|
|
|
|
static const guint8 crc8_table[256] = {
|
|
|
|
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
|
|
|
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
|
|
|
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
|
|
|
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
|
|
|
|
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
|
|
|
|
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
|
|
|
|
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
|
|
|
|
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
|
|
|
|
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
|
|
|
|
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
|
|
|
|
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
|
|
|
|
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
|
|
|
|
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
|
|
|
|
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
|
|
|
|
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
|
|
|
|
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
|
|
|
|
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
|
|
|
|
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
|
|
|
|
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
|
|
|
|
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
|
|
|
|
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
|
|
|
|
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
|
|
|
|
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
|
|
|
|
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
|
|
|
|
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
|
|
|
|
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
|
|
|
|
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
|
|
|
|
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
|
|
|
|
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
|
|
|
|
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
|
|
|
|
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
|
|
|
|
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint8
|
2014-06-10 09:52:23 +00:00
|
|
|
gst_flac_calculate_crc8 (const guint8 * data, guint length)
|
2006-04-07 18:15:08 +00:00
|
|
|
{
|
|
|
|
guint8 crc = 0;
|
|
|
|
|
|
|
|
while (length--) {
|
|
|
|
crc = crc8_table[crc ^ *data];
|
|
|
|
++data;
|
|
|
|
}
|
|
|
|
|
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
|
2011-10-30 18:45:45 +00:00
|
|
|
/* FIXME: for our purposes it's probably enough to just check for the sync
|
|
|
|
* marker - we just want to know if it's a header frame or not */
|
2006-04-07 18:15:08 +00:00
|
|
|
static gboolean
|
2014-06-10 09:52:23 +00:00
|
|
|
gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, const guint8 * data,
|
|
|
|
guint size)
|
2006-04-07 18:15:08 +00:00
|
|
|
{
|
|
|
|
guint headerlen;
|
|
|
|
guint sr_from_end = 0; /* can be 0, 8 or 16 */
|
|
|
|
guint bs_from_end = 0; /* can be 0, 8 or 16 */
|
|
|
|
guint32 val = 0;
|
|
|
|
guint8 bs, sr, ca, ss, pb;
|
2014-05-10 07:14:33 +00:00
|
|
|
gboolean vbs;
|
2006-04-07 18:15:08 +00:00
|
|
|
|
|
|
|
if (size < 10)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* sync */
|
2011-08-16 14:22:46 +00:00
|
|
|
if (data[0] != 0xFF || (data[1] & 0xFC) != 0xF8)
|
2006-04-07 18:15:08 +00:00
|
|
|
return FALSE;
|
|
|
|
|
2014-05-10 07:14:33 +00:00
|
|
|
vbs = ! !(data[1] & 1); /* variable blocksize */
|
2011-08-16 14:27:43 +00:00
|
|
|
bs = (data[2] & 0xF0) >> 4; /* blocksize marker */
|
2006-04-07 18:15:08 +00:00
|
|
|
sr = (data[2] & 0x0F); /* samplerate marker */
|
2011-08-16 14:27:43 +00:00
|
|
|
ca = (data[3] & 0xF0) >> 4; /* channel assignment */
|
2006-04-07 18:15:08 +00:00
|
|
|
ss = (data[3] & 0x0F) >> 1; /* sample size marker */
|
|
|
|
pb = (data[3] & 0x01); /* padding bit */
|
|
|
|
|
2009-02-05 19:02:01 +00:00
|
|
|
GST_LOG_OBJECT (flacdec,
|
2014-05-10 07:14:33 +00:00
|
|
|
"got sync, vbs=%d,bs=%x,sr=%x,ca=%x,ss=%x,pb=%x", vbs, bs, sr, ca, ss,
|
|
|
|
pb);
|
2006-04-07 18:15:08 +00:00
|
|
|
|
2011-08-16 14:32:07 +00:00
|
|
|
if (bs == 0 || sr == 0x0F || ca >= 0x0B || ss == 0x03 || ss == 0x07) {
|
2006-04-07 18:15:08 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* read block size from end of header? */
|
|
|
|
if (bs == 6)
|
|
|
|
bs_from_end = 8;
|
|
|
|
else if (bs == 7)
|
|
|
|
bs_from_end = 16;
|
|
|
|
|
|
|
|
/* read sample rate from end of header? */
|
|
|
|
if (sr == 0x0C)
|
|
|
|
sr_from_end = 8;
|
|
|
|
else if (sr == 0x0D || sr == 0x0E)
|
|
|
|
sr_from_end = 16;
|
|
|
|
|
2012-08-03 12:02:23 +00:00
|
|
|
val = data[4];
|
|
|
|
/* This is slightly faster than a loop */
|
|
|
|
if (!(val & 0x80)) {
|
|
|
|
val = 0;
|
|
|
|
} else if ((val & 0xc0) && !(val & 0x20)) {
|
|
|
|
val = 1;
|
|
|
|
} else if ((val & 0xe0) && !(val & 0x10)) {
|
|
|
|
val = 2;
|
|
|
|
} else if ((val & 0xf0) && !(val & 0x08)) {
|
|
|
|
val = 3;
|
|
|
|
} else if ((val & 0xf8) && !(val & 0x04)) {
|
|
|
|
val = 4;
|
|
|
|
} else if ((val & 0xfc) && !(val & 0x02)) {
|
|
|
|
val = 5;
|
|
|
|
} else if ((val & 0xfe) && !(val & 0x01)) {
|
|
|
|
val = 6;
|
|
|
|
} else {
|
|
|
|
GST_LOG_OBJECT (flacdec, "failed to read sample/frame");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
val++;
|
|
|
|
headerlen = 4 + val + (bs_from_end / 8) + (sr_from_end / 8);
|
|
|
|
|
|
|
|
if (gst_flac_calculate_crc8 (data, headerlen) != data[headerlen]) {
|
|
|
|
GST_LOG_OBJECT (flacdec, "invalid checksum");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-04-07 18:15:08 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2012-03-16 17:23:29 +00:00
|
|
|
static gboolean
|
|
|
|
gst_flac_dec_handle_decoder_error (GstFlacDec * dec, gboolean msg)
|
|
|
|
{
|
|
|
|
gboolean ret;
|
|
|
|
|
|
|
|
dec->error_count++;
|
|
|
|
if (dec->error_count > 10) {
|
|
|
|
if (msg)
|
|
|
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL));
|
|
|
|
dec->last_flow = GST_FLOW_ERROR;
|
|
|
|
ret = TRUE;
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (dec, "ignoring error for now at count %d",
|
|
|
|
dec->error_count);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
static void
|
2009-08-01 15:48:36 +00:00
|
|
|
gst_flac_dec_metadata_cb (const FLAC__StreamDecoder * decoder,
|
|
|
|
const FLAC__StreamMetadata * metadata, void *client_data)
|
2002-06-07 20:09:05 +00:00
|
|
|
{
|
2009-08-01 15:48:36 +00:00
|
|
|
GstFlacDec *flacdec = GST_FLAC_DEC (client_data);
|
2014-06-04 11:11:10 +00:00
|
|
|
GstAudioChannelPosition position[8];
|
2009-08-01 15:48:36 +00:00
|
|
|
|
|
|
|
GST_LOG_OBJECT (flacdec, "metadata type: %d", metadata->type);
|
|
|
|
|
2004-03-14 22:34:33 +00:00
|
|
|
switch (metadata->type) {
|
2006-04-07 18:15:08 +00:00
|
|
|
case FLAC__METADATA_TYPE_STREAMINFO:{
|
|
|
|
gint64 samples;
|
2014-06-04 11:11:10 +00:00
|
|
|
guint depth, width, gdepth, channels;
|
2006-04-07 18:15:08 +00:00
|
|
|
|
|
|
|
samples = metadata->data.stream_info.total_samples;
|
|
|
|
|
|
|
|
flacdec->min_blocksize = metadata->data.stream_info.min_blocksize;
|
|
|
|
flacdec->max_blocksize = metadata->data.stream_info.max_blocksize;
|
2010-03-26 13:16:39 +00:00
|
|
|
flacdec->depth = depth = metadata->data.stream_info.bits_per_sample;
|
|
|
|
|
2012-07-25 13:29:04 +00:00
|
|
|
if (depth < 9) {
|
|
|
|
gdepth = width = 8;
|
|
|
|
} else if (depth < 17) {
|
|
|
|
gdepth = width = 16;
|
|
|
|
} else if (depth < 25) {
|
|
|
|
gdepth = 24;
|
2012-01-06 08:40:22 +00:00
|
|
|
width = 32;
|
2012-07-25 13:29:04 +00:00
|
|
|
} else {
|
|
|
|
gdepth = width = 32;
|
|
|
|
}
|
2012-01-06 08:40:22 +00:00
|
|
|
|
2014-06-04 11:11:10 +00:00
|
|
|
channels = metadata->data.stream_info.channels;
|
|
|
|
memcpy (position, channel_positions[channels - 1], sizeof (position));
|
|
|
|
gst_audio_channel_positions_to_valid_order (position, channels);
|
|
|
|
/* Note: we create the inverse reordering map here */
|
|
|
|
gst_audio_get_channel_reorder_map (channels,
|
|
|
|
position, channel_positions[channels - 1],
|
|
|
|
flacdec->channel_reorder_map);
|
|
|
|
|
2012-01-06 08:40:22 +00:00
|
|
|
gst_audio_info_set_format (&flacdec->info,
|
2012-07-25 13:29:04 +00:00
|
|
|
gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth),
|
2012-01-06 08:40:22 +00:00
|
|
|
metadata->data.stream_info.sample_rate,
|
2014-06-04 11:11:10 +00:00
|
|
|
metadata->data.stream_info.channels, position);
|
2006-04-07 18:15:08 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (flacdec, "blocksize: min=%u, max=%u",
|
|
|
|
flacdec->min_blocksize, flacdec->max_blocksize);
|
2010-03-26 13:16:39 +00:00
|
|
|
GST_DEBUG_OBJECT (flacdec, "sample rate: %u, channels: %u",
|
2012-01-06 08:40:22 +00:00
|
|
|
flacdec->info.rate, flacdec->info.channels);
|
2010-03-26 13:16:39 +00:00
|
|
|
GST_DEBUG_OBJECT (flacdec, "depth: %u, width: %u", flacdec->depth,
|
2012-01-06 08:40:22 +00:00
|
|
|
flacdec->info.finfo->width);
|
2006-04-07 18:15:08 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (flacdec, "total samples = %" G_GINT64_FORMAT, samples);
|
2004-03-14 22:34:33 +00:00
|
|
|
break;
|
2006-04-07 18:15:08 +00:00
|
|
|
}
|
2003-04-27 12:00:41 +00:00
|
|
|
default:
|
2004-03-14 22:34:33 +00:00
|
|
|
break;
|
2003-04-27 12:00:41 +00:00
|
|
|
}
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
|
|
|
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
static void
|
2009-08-01 15:48:36 +00:00
|
|
|
gst_flac_dec_error_cb (const FLAC__StreamDecoder * d,
|
|
|
|
FLAC__StreamDecoderErrorStatus status, void *client_data)
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
{
|
|
|
|
const gchar *error;
|
2009-08-01 15:48:36 +00:00
|
|
|
GstFlacDec *dec;
|
|
|
|
|
|
|
|
dec = GST_FLAC_DEC (client_data);
|
2002-06-07 20:09:05 +00:00
|
|
|
|
|
|
|
switch (status) {
|
2002-07-08 19:31:49 +00:00
|
|
|
case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
/* Ignore this error and keep processing */
|
|
|
|
return;
|
2002-07-08 19:31:49 +00:00
|
|
|
case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:
|
2002-06-07 20:09:05 +00:00
|
|
|
error = "bad header";
|
|
|
|
break;
|
2002-07-08 19:31:49 +00:00
|
|
|
case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:
|
2002-06-07 20:09:05 +00:00
|
|
|
error = "CRC mismatch";
|
|
|
|
break;
|
|
|
|
default:
|
2004-02-16 17:09:18 +00:00
|
|
|
error = "unknown error";
|
2002-06-07 20:09:05 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2012-03-16 17:23:29 +00:00
|
|
|
if (gst_flac_dec_handle_decoder_error (dec, FALSE))
|
|
|
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), ("%s (%d)", error, status));
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
}
|
|
|
|
|
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
Original commit message from CVS:
Patch by: Josh Coalson <xflac at yahoo dot com>,
updated by Alexis Ballier <aballier at gentoo dot org>:
* configure.ac:
* ext/flac/gstflacdec.c: (gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_seek),
(gst_flac_dec_tell), (gst_flac_dec_length), (gst_flac_dec_eof),
(gst_flac_dec_read_seekable), (gst_flac_dec_read_stream):
* ext/flac/gstflacdec.h:
* ext/flac/gstflacenc.c: (gst_flac_enc_init),
(gst_flac_enc_finalize), (gst_flac_enc_set_metadata),
(gst_flac_enc_sink_setcaps), (gst_flac_enc_update_quality),
(gst_flac_enc_seek_callback), (gst_flac_enc_write_callback),
(gst_flac_enc_tell_callback), (gst_flac_enc_sink_event),
(gst_flac_enc_chain), (gst_flac_enc_set_property),
(gst_flac_enc_get_property), (gst_flac_enc_change_state):
* ext/flac/gstflacenc.h:
Add support for flac >= 1.1.3 which changed the API. Fixes bug #385887.
2007-06-10 10:53:26 +00:00
|
|
|
static FLAC__StreamDecoderReadStatus
|
|
|
|
gst_flac_dec_read_stream (const FLAC__StreamDecoder * decoder,
|
|
|
|
FLAC__byte buffer[], size_t * bytes, void *client_data)
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
{
|
|
|
|
GstFlacDec *dec = GST_FLAC_DEC (client_data);
|
|
|
|
guint len;
|
|
|
|
|
|
|
|
len = MIN (gst_adapter_available (dec->adapter), *bytes);
|
|
|
|
|
|
|
|
if (len == 0) {
|
|
|
|
GST_LOG_OBJECT (dec, "0 bytes available at the moment");
|
|
|
|
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
|
|
|
|
}
|
|
|
|
|
2011-11-22 01:40:39 +00:00
|
|
|
GST_LOG_OBJECT (dec, "feeding %u bytes to decoder "
|
|
|
|
"(available=%" G_GSIZE_FORMAT ", bytes=%u)",
|
2008-10-10 12:28:34 +00:00
|
|
|
len, gst_adapter_available (dec->adapter), (guint) * bytes);
|
2009-08-01 14:22:49 +00:00
|
|
|
gst_adapter_copy (dec->adapter, buffer, 0, len);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
*bytes = len;
|
|
|
|
|
|
|
|
gst_adapter_flush (dec->adapter, len);
|
|
|
|
|
|
|
|
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
|
|
|
}
|
|
|
|
|
2001-12-23 14:15:30 +00:00
|
|
|
static FLAC__StreamDecoderWriteStatus
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
|
|
|
|
const FLAC__int32 * const buffer[])
|
2001-12-23 14:15:30 +00:00
|
|
|
{
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
GstFlowReturn ret = GST_FLOW_OK;
|
2001-12-23 14:15:30 +00:00
|
|
|
GstBuffer *outbuf;
|
|
|
|
guint depth = frame->header.bits_per_sample;
|
2012-07-25 13:29:04 +00:00
|
|
|
guint width, gdepth;
|
2010-03-26 13:16:39 +00:00
|
|
|
guint sample_rate = frame->header.sample_rate;
|
2001-12-23 14:15:30 +00:00
|
|
|
guint channels = frame->header.channels;
|
|
|
|
guint samples = frame->header.blocksize;
|
|
|
|
guint j, i;
|
2012-01-24 13:38:58 +00:00
|
|
|
GstMapInfo map;
|
2012-01-06 08:40:22 +00:00
|
|
|
gboolean caps_changed;
|
2014-06-04 11:11:10 +00:00
|
|
|
GstAudioChannelPosition chanpos[8];
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
|
2009-03-02 07:41:15 +00:00
|
|
|
GST_LOG_OBJECT (flacdec, "samples in frame header: %d", samples);
|
|
|
|
|
2011-09-28 15:40:01 +00:00
|
|
|
if (depth == 0) {
|
|
|
|
if (flacdec->depth < 4 || flacdec->depth > 32) {
|
|
|
|
GST_ERROR_OBJECT (flacdec, "unsupported depth %d from STREAMINFO",
|
|
|
|
flacdec->depth);
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
depth = flacdec->depth;
|
|
|
|
}
|
|
|
|
|
2005-12-09 11:12:48 +00:00
|
|
|
switch (depth) {
|
|
|
|
case 8:
|
2012-07-25 13:29:04 +00:00
|
|
|
gdepth = width = 8;
|
2005-12-09 11:12:48 +00:00
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
case 16:
|
2012-07-25 13:29:04 +00:00
|
|
|
gdepth = width = 16;
|
2005-12-09 11:12:48 +00:00
|
|
|
break;
|
|
|
|
case 20:
|
|
|
|
case 24:
|
2012-07-25 13:29:04 +00:00
|
|
|
gdepth = 24;
|
2005-12-09 11:12:48 +00:00
|
|
|
width = 32;
|
|
|
|
break;
|
2012-07-25 13:29:04 +00:00
|
|
|
case 32:
|
|
|
|
gdepth = width = 32;
|
|
|
|
break;
|
2005-12-09 11:12:48 +00:00
|
|
|
default:
|
2007-12-29 16:48:33 +00:00
|
|
|
GST_ERROR_OBJECT (flacdec, "unsupported depth %d", depth);
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto done;
|
2002-06-07 20:09:05 +00:00
|
|
|
}
|
2004-03-14 22:34:33 +00:00
|
|
|
|
2010-03-26 13:16:39 +00:00
|
|
|
if (sample_rate == 0) {
|
2012-01-06 08:40:22 +00:00
|
|
|
if (flacdec->info.rate != 0) {
|
|
|
|
sample_rate = flacdec->info.rate;
|
2010-03-26 13:16:39 +00:00
|
|
|
} else {
|
|
|
|
GST_ERROR_OBJECT (flacdec, "unknown sample rate");
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-25 13:29:04 +00:00
|
|
|
caps_changed = (sample_rate != GST_AUDIO_INFO_RATE (&flacdec->info))
|
|
|
|
|| (width != GST_AUDIO_INFO_WIDTH (&flacdec->info))
|
|
|
|
|| (gdepth != GST_AUDIO_INFO_DEPTH (&flacdec->info))
|
|
|
|
|| (channels != GST_AUDIO_INFO_CHANNELS (&flacdec->info));
|
2012-01-06 08:40:22 +00:00
|
|
|
|
|
|
|
if (caps_changed
|
|
|
|
|| !gst_pad_has_current_caps (GST_AUDIO_DECODER_SRC_PAD (flacdec))) {
|
|
|
|
GST_DEBUG_OBJECT (flacdec, "Negotiating %d Hz @ %d channels", sample_rate,
|
|
|
|
channels);
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
|
2014-06-04 11:11:10 +00:00
|
|
|
memcpy (chanpos, channel_positions[flacdec->info.channels - 1],
|
|
|
|
sizeof (chanpos));
|
|
|
|
gst_audio_channel_positions_to_valid_order (chanpos,
|
|
|
|
flacdec->info.channels);
|
2012-01-06 08:40:22 +00:00
|
|
|
gst_audio_info_set_format (&flacdec->info,
|
2012-07-25 13:29:04 +00:00
|
|
|
gst_audio_format_build_integer (TRUE, G_BYTE_ORDER, width, gdepth),
|
2014-06-04 11:11:10 +00:00
|
|
|
sample_rate, channels, chanpos);
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
|
2012-01-06 08:40:22 +00:00
|
|
|
/* Note: we create the inverse reordering map here */
|
|
|
|
gst_audio_get_channel_reorder_map (flacdec->info.channels,
|
|
|
|
flacdec->info.position, channel_positions[flacdec->info.channels - 1],
|
|
|
|
flacdec->channel_reorder_map);
|
2008-05-25 16:09:39 +00:00
|
|
|
|
2002-06-07 20:09:05 +00:00
|
|
|
flacdec->depth = depth;
|
2007-12-18 17:40:34 +00:00
|
|
|
|
2012-02-01 15:05:51 +00:00
|
|
|
gst_audio_decoder_set_output_format (GST_AUDIO_DECODER (flacdec),
|
|
|
|
&flacdec->info);
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
|
|
|
|
2012-03-15 12:36:17 +00:00
|
|
|
outbuf =
|
|
|
|
gst_buffer_new_allocate (NULL, samples * channels * (width / 8), NULL);
|
2009-03-09 16:14:12 +00:00
|
|
|
|
2012-01-24 13:38:58 +00:00
|
|
|
gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
|
2008-08-03 11:38:22 +00:00
|
|
|
if (width == 8) {
|
2012-01-24 13:38:58 +00:00
|
|
|
gint8 *outbuffer = (gint8 *) map.data;
|
2012-01-06 08:40:22 +00:00
|
|
|
gint *reorder_map = flacdec->channel_reorder_map;
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
|
2014-04-30 17:06:40 +00:00
|
|
|
g_assert (gdepth == 8 && depth == 8);
|
|
|
|
for (i = 0; i < samples; i++) {
|
|
|
|
for (j = 0; j < channels; j++) {
|
|
|
|
*outbuffer++ = (gint8) buffer[reorder_map[j]][i];
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
}
|
2008-08-03 11:38:22 +00:00
|
|
|
} else if (width == 16) {
|
2012-01-24 13:38:58 +00:00
|
|
|
gint16 *outbuffer = (gint16 *) map.data;
|
2012-01-06 08:40:22 +00:00
|
|
|
gint *reorder_map = flacdec->channel_reorder_map;
|
|
|
|
|
2012-07-25 13:29:04 +00:00
|
|
|
if (gdepth != depth) {
|
2012-01-06 08:40:22 +00:00
|
|
|
for (i = 0; i < samples; i++) {
|
|
|
|
for (j = 0; j < channels; j++) {
|
|
|
|
*outbuffer++ =
|
2012-07-25 13:29:04 +00:00
|
|
|
(gint16) (buffer[reorder_map[j]][i] << (gdepth - depth));
|
2012-01-06 08:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < samples; i++) {
|
|
|
|
for (j = 0; j < channels; j++) {
|
|
|
|
*outbuffer++ = (gint16) buffer[reorder_map[j]][i];
|
|
|
|
}
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
2003-06-28 14:21:47 +00:00
|
|
|
}
|
2008-08-03 11:38:22 +00:00
|
|
|
} else if (width == 32) {
|
2012-01-24 13:38:58 +00:00
|
|
|
gint32 *outbuffer = (gint32 *) map.data;
|
2012-01-06 08:40:22 +00:00
|
|
|
gint *reorder_map = flacdec->channel_reorder_map;
|
|
|
|
|
2012-07-25 13:29:04 +00:00
|
|
|
if (gdepth != depth) {
|
2012-01-06 08:40:22 +00:00
|
|
|
for (i = 0; i < samples; i++) {
|
|
|
|
for (j = 0; j < channels; j++) {
|
|
|
|
*outbuffer++ =
|
2012-07-25 13:29:04 +00:00
|
|
|
(gint32) (buffer[reorder_map[j]][i] << (gdepth - depth));
|
2012-01-06 08:40:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < samples; i++) {
|
|
|
|
for (j = 0; j < channels; j++) {
|
|
|
|
*outbuffer++ = (gint32) buffer[reorder_map[j]][i];
|
|
|
|
}
|
2005-09-06 21:31:25 +00:00
|
|
|
}
|
|
|
|
}
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
} else {
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
g_assert_not_reached ();
|
Port flacdec (seeking is still slow'ish).
Original commit message from CVS:
* configure.ac:
* ext/Makefile.am:
* ext/flac/Makefile.am:
* ext/flac/gstflac.c: (plugin_init):
* ext/flac/gstflacdec.c: (flacdec_get_type), (gst_flacdec_init),
(gst_flacdec_update_metadata), (gst_flacdec_seek),
(gst_flacdec_tell), (gst_flacdec_length), (gst_flacdec_read),
(gst_flacdec_write), (gst_flacdec_loop),
(gst_flacdec_get_src_query_types), (gst_flacdec_src_query),
(gst_flacdec_src_event), (gst_flacdec_sink_activate),
(gst_flacdec_sink_activate_pull), (gst_flacdec_change_state):
* ext/flac/gstflacdec.h:
Port flacdec (seeking is still slow'ish).
2005-08-22 11:20:18 +00:00
|
|
|
}
|
2012-01-24 13:38:58 +00:00
|
|
|
gst_buffer_unmap (outbuf, &map);
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
|
2011-10-30 18:45:45 +00:00
|
|
|
GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
|
2012-03-16 17:23:29 +00:00
|
|
|
if (flacdec->error_count)
|
|
|
|
flacdec->error_count--;
|
2011-09-28 17:32:00 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
if (G_UNLIKELY (ret != GST_FLOW_OK)) {
|
|
|
|
GST_DEBUG_OBJECT (flacdec, "finish_frame flow %s", gst_flow_get_name (ret));
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
/* we act on the flow return value later in the handle_frame function, as we
|
|
|
|
* don't want to mess up the internal decoder state by returning ABORT when
|
|
|
|
* the error is in fact non-fatal (like a pad in flushing mode) and we want
|
ext/flac/gstflacdec.*: Rewrite flacdec a bit, so that even seeking might work now. Most importantly, don't act upon a...
Original commit message from CVS:
* ext/flac/gstflacdec.c: (gst_flac_dec_base_init),
(gst_flac_dec_class_init), (gst_flac_dec_init),
(gst_flac_dec_metadata_callback), (gst_flac_dec_error_callback),
(gst_flac_dec_eof), (gst_flac_dec_write), (gst_flac_dec_loop),
(gst_flac_dec_convert_src), (gst_flac_dec_get_src_query_types),
(gst_flac_dec_src_query), (gst_flac_dec_send_newsegment),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_src_event),
(gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Rewrite flacdec a bit, so that even seeking might work now. Most
importantly, don't act upon any flow return values we get, just tell
the decoder everything's dandy and act on the flow return values
later on in the loop function. We don't want to mess up the internal
decoder state for non-fatal things like flushing pads etc. Other
than that, use GstSegment (segment seeks don't work yet though, but
should be easy to add), use boilerplate macros, drop the superfluous
'flacdec:' from debug messages, use gst_util_uint64_scale_int, and
lots of other things.
2005-12-10 20:26:33 +00:00
|
|
|
* to continue later. So just pretend everything's dandy and act later. */
|
|
|
|
flacdec->last_flow = ret;
|
2002-06-07 20:09:05 +00:00
|
|
|
|
2002-07-08 19:31:49 +00:00
|
|
|
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
2001-12-23 14:15:30 +00:00
|
|
|
}
|
|
|
|
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
static FLAC__StreamDecoderWriteStatus
|
|
|
|
gst_flac_dec_write_stream (const FLAC__StreamDecoder * decoder,
|
|
|
|
const FLAC__Frame * frame,
|
|
|
|
const FLAC__int32 * const buffer[], void *client_data)
|
|
|
|
{
|
|
|
|
return gst_flac_dec_write (GST_FLAC_DEC (client_data), frame, buffer);
|
|
|
|
}
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
static void
|
|
|
|
gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard)
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
{
|
2011-10-09 15:18:09 +00:00
|
|
|
GstFlacDec *dec = GST_FLAC_DEC (audio_dec);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
if (!hard) {
|
|
|
|
guint available = gst_adapter_available (dec->adapter);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
if (available > 0) {
|
|
|
|
GST_INFO_OBJECT (dec, "draining, %u bytes left in adapter", available);
|
|
|
|
FLAC__stream_decoder_process_until_end_of_stream (dec->decoder);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
FLAC__stream_decoder_flush (dec->decoder);
|
|
|
|
gst_adapter_clear (dec->adapter);
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static GstFlowReturn
|
2011-10-09 15:18:09 +00:00
|
|
|
gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
{
|
|
|
|
GstFlacDec *dec;
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
dec = GST_FLAC_DEC (audio_dec);
|
|
|
|
|
|
|
|
/* drain remaining data? */
|
|
|
|
if (G_UNLIKELY (buf == NULL)) {
|
|
|
|
gst_flac_dec_flush (audio_dec, FALSE);
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
|
|
|
|
2011-11-22 01:40:39 +00:00
|
|
|
GST_LOG_OBJECT (dec, "frame: ts %" GST_TIME_FORMAT ", flags 0x%04x, "
|
|
|
|
"%" G_GSIZE_FORMAT " bytes", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
|
|
|
|
GST_BUFFER_FLAGS (buf), gst_buffer_get_size (buf));
|
2011-10-09 15:18:09 +00:00
|
|
|
|
2011-10-30 18:45:45 +00:00
|
|
|
/* drop any in-stream headers, we've processed those in set_format already */
|
2011-10-09 15:18:09 +00:00
|
|
|
if (G_UNLIKELY (!dec->got_headers)) {
|
2011-10-30 18:45:45 +00:00
|
|
|
gboolean got_audio_frame;
|
2012-01-24 13:38:58 +00:00
|
|
|
GstMapInfo map;
|
2006-08-22 12:28:24 +00:00
|
|
|
|
|
|
|
/* check if this is a flac audio frame (rather than a header or junk) */
|
2012-01-24 13:38:58 +00:00
|
|
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
2014-05-10 07:14:33 +00:00
|
|
|
got_audio_frame = gst_flac_dec_scan_got_frame (dec, map.data, map.size);
|
2012-01-24 13:38:58 +00:00
|
|
|
gst_buffer_unmap (buf, &map);
|
2011-10-30 18:45:45 +00:00
|
|
|
|
|
|
|
if (!got_audio_frame) {
|
2011-11-22 01:40:39 +00:00
|
|
|
GST_INFO_OBJECT (dec, "dropping in-stream header, %" G_GSIZE_FORMAT " "
|
2012-01-24 13:38:58 +00:00
|
|
|
"bytes", map.size);
|
2011-11-15 13:23:56 +00:00
|
|
|
gst_audio_decoder_finish_frame (audio_dec, NULL, 1);
|
2011-10-30 18:45:45 +00:00
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
|
|
|
|
dec->got_headers = TRUE;
|
2006-08-22 12:28:24 +00:00
|
|
|
}
|
|
|
|
|
2011-10-09 15:18:09 +00:00
|
|
|
gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
buf = NULL;
|
|
|
|
|
|
|
|
dec->last_flow = GST_FLOW_OK;
|
|
|
|
|
2011-10-30 18:45:45 +00:00
|
|
|
/* framed - there should always be enough data to decode something */
|
2011-11-22 01:40:39 +00:00
|
|
|
GST_LOG_OBJECT (dec, "%" G_GSIZE_FORMAT " bytes available",
|
2011-10-30 18:45:45 +00:00
|
|
|
gst_adapter_available (dec->adapter));
|
2009-02-05 23:51:42 +00:00
|
|
|
|
2011-10-30 18:45:45 +00:00
|
|
|
if (!FLAC__stream_decoder_process_single (dec->decoder)) {
|
|
|
|
GST_INFO_OBJECT (dec, "process_single failed");
|
2015-06-26 04:24:17 +00:00
|
|
|
if (FLAC__stream_decoder_get_state (dec->decoder) ==
|
|
|
|
FLAC__STREAM_DECODER_ABORTED) {
|
|
|
|
GST_WARNING_OBJECT (dec, "Read callback caused internal abort");
|
|
|
|
/* allow recovery */
|
|
|
|
gst_adapter_clear (dec->adapter);
|
|
|
|
FLAC__stream_decoder_flush (dec->decoder);
|
|
|
|
gst_flac_dec_handle_decoder_error (dec, TRUE);
|
|
|
|
}
|
ext/flac/: Support chain-based operation, should make flac-over-DAAP work (#340492).
Original commit message from CVS:
* ext/flac/Makefile.am:
* ext/flac/gstflacdec.c: (gst_flac_dec_init),
(gst_flac_dec_reset_decoders),
(gst_flac_dec_setup_seekable_decoder),
(gst_flac_dec_setup_stream_decoder), (gst_flac_dec_finalize),
(gst_flac_dec_metadata_callback),
(gst_flac_dec_metadata_callback_seekable),
(gst_flac_dec_metadata_callback_stream),
(gst_flac_dec_error_callback),
(gst_flac_dec_error_callback_seekable),
(gst_flac_dec_error_callback_stream), (gst_flac_dec_read_seekable),
(gst_flac_dec_read_stream), (gst_flac_dec_write),
(gst_flac_dec_write_seekable), (gst_flac_dec_write_stream),
(gst_flac_dec_loop), (gst_flac_dec_sink_event),
(gst_flac_dec_chain), (gst_flac_dec_convert_sink),
(gst_flac_dec_get_sink_query_types), (gst_flac_dec_sink_query),
(gst_flac_dec_get_src_query_types), (gst_flac_dec_src_query),
(gst_flac_dec_handle_seek_event), (gst_flac_dec_sink_activate),
(gst_flac_dec_sink_activate_push),
(gst_flac_dec_sink_activate_pull), (gst_flac_dec_change_state):
* ext/flac/gstflacdec.h:
Support chain-based operation, should make flac-over-DAAP
work (#340492).
2006-06-20 19:40:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return dec->last_flow;
|
|
|
|
}
|