From 8a0d06c3aec406f63ec2cc7e79baf5799274ec16 Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 1 Sep 2005 17:31:21 +0000 Subject: [PATCH] AC3 -> IEC958 (S/PDIF) framer, based on Martin Soto's 0.8 plugin Original commit message from CVS: AC3 -> IEC958 (S/PDIF) framer, based on Martin Soto's 0.8 plugin --- ChangeLog | 14 ++ configure.ac | 2 + gst/iec958/Makefile.am | 9 ++ gst/iec958/ac3_padder.c | 250 ++++++++++++++++++++++++++++++ gst/iec958/ac3_padder.h | 138 +++++++++++++++++ gst/iec958/ac3iec.c | 331 ++++++++++++++++++++++++++++++++++++++++ gst/iec958/ac3iec.h | 79 ++++++++++ 7 files changed, 823 insertions(+) create mode 100644 gst/iec958/Makefile.am create mode 100644 gst/iec958/ac3_padder.c create mode 100644 gst/iec958/ac3_padder.h create mode 100644 gst/iec958/ac3iec.c create mode 100644 gst/iec958/ac3iec.h diff --git a/ChangeLog b/ChangeLog index 0ca5976b66..e168c183e6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2005-09-01 Michael Smith + + * configure.ac: + * gst/iec958/Makefile.am: + * gst/iec958/ac3_padder.c: (ac3p_init), (ac3p_push_data), + (ac3p_parse): + * gst/iec958/ac3_padder.h: + * gst/iec958/ac3iec.c: (ac3iec_get_type), (ac3iec_base_init), + (ac3iec_class_init), (ac3iec_init), (ac3iec_finalize), + (ac3iec_set_property), (ac3iec_get_property), (ac3iec_chain), + (ac3iec_change_state), (plugin_init): + * gst/iec958/ac3iec.h: + AC3 -> IEC958 (S/PDIF) framer, port of Martin Soto's 0.8 plugin. + 2005-09-01 Wim Taymans * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcmdec_setcaps), diff --git a/configure.ac b/configure.ac index 3d39941141..7eb0ed257a 100644 --- a/configure.ac +++ b/configure.ac @@ -215,6 +215,7 @@ AC_SUBST(GST_PLUGIN_LDFLAGS) dnl these are all the gst plug-ins, compilable without additional libs GST_PLUGINS_ALL="\ dvdlpcmdec \ + iec958 \ mpegaudioparse \ realmedia \ " @@ -382,6 +383,7 @@ AC_CONFIG_FILES( Makefile gst/Makefile gst/dvdlpcmdec/Makefile +gst/iec958/Makefile gst/mpegaudioparse/Makefile gst/realmedia/Makefile ext/Makefile diff --git a/gst/iec958/Makefile.am b/gst/iec958/Makefile.am new file mode 100644 index 0000000000..a83dce9476 --- /dev/null +++ b/gst/iec958/Makefile.am @@ -0,0 +1,9 @@ +plugin_LTLIBRARIES = libiec958.la + +libiec958_la_SOURCES = ac3iec.c ac3_padder.c +libiec958_la_CFLAGS = $(GLIB_CFLAGS) $(GST_CFLAGS) \ + $(GSTLIBS_CFLAGS) $(EXTRA_CFLAGS) +libiec958_la_LIBADD = $(GLIB_LIBS) $(GST_LIBS) $(GSTLIBS_LIBS) +libiec958_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +noinst_HEADERS = ac3_padder.h ac3iec.h diff --git a/gst/iec958/ac3_padder.c b/gst/iec958/ac3_padder.c new file mode 100644 index 0000000000..9ec551de6b --- /dev/null +++ b/gst/iec958/ac3_padder.c @@ -0,0 +1,250 @@ +/* GStreamer + * Copyright (C) 2003, 2004 Martin Soto + * + * ac3_padder.c: Pad AC3 frames for use with an SPDIF interface. + * + * 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 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "ac3_padder.h" + +#define IEC61937_DATA_TYPE_AC3 1 + +struct frmsize_s +{ + unsigned short bit_rate; + unsigned short frm_size[3]; +}; + + +static const struct frmsize_s frmsizecod_tbl[64] = { + {32, {64, 69, 96}}, + {32, {64, 70, 96}}, + {40, {80, 87, 120}}, + {40, {80, 88, 120}}, + {48, {96, 104, 144}}, + {48, {96, 105, 144}}, + {56, {112, 121, 168}}, + {56, {112, 122, 168}}, + {64, {128, 139, 192}}, + {64, {128, 140, 192}}, + {80, {160, 174, 240}}, + {80, {160, 175, 240}}, + {96, {192, 208, 288}}, + {96, {192, 209, 288}}, + {112, {224, 243, 336}}, + {112, {224, 244, 336}}, + {128, {256, 278, 384}}, + {128, {256, 279, 384}}, + {160, {320, 348, 480}}, + {160, {320, 349, 480}}, + {192, {384, 417, 576}}, + {192, {384, 418, 576}}, + {224, {448, 487, 672}}, + {224, {448, 488, 672}}, + {256, {512, 557, 768}}, + {256, {512, 558, 768}}, + {320, {640, 696, 960}}, + {320, {640, 697, 960}}, + {384, {768, 835, 1152}}, + {384, {768, 836, 1152}}, + {448, {896, 975, 1344}}, + {448, {896, 976, 1344}}, + {512, {1024, 1114, 1536}}, + {512, {1024, 1115, 1536}}, + {576, {1152, 1253, 1728}}, + {576, {1152, 1254, 1728}}, + {640, {1280, 1393, 1920}}, + {640, {1280, 1394, 1920}} +}; + + + +/* Go one byte forward in the input buffer. */ +#define ac3p_in_fw(padder) ((padder)->in_ptr++, (padder)->remaining--) + +/* Go one byte forward in the output buffer. */ +#define ac3p_out_fw(padder) ((padder)->out_ptr++, (padder)->bytes_to_copy--) + + +/** + * ac3p_init + * @padder: The padder structure to initialize. + * + * Initializes an AC3 stream padder. This structure can be + * subsequently used to parse an AC3 stream and convert it to IEC958 + * (S/PDIF) padded packets. + */ +extern void +ac3p_init (ac3_padder * padder) +{ + const char sync[4] = { 0x72, 0xF8, 0x1F, 0x4E }; + + padder->state = AC3P_STATE_SYNC1; + + /* No material to read yet. */ + padder->remaining = 0; + + /* Initialize the sync bytes in the frame. */ + memcpy (padder->frame.header, sync, 4); +} + + +/** + * ac3_push_data + * @padder The padder structure. + * @data A pointer to a buffer with new data to parse. This should + * correspond to a new piece of a stream containing raw AC3 data. + * @size The number of available bytes in the buffer. + * + * Pushes a new buffer of data to be parsed by the ac3 padder. The + * ac3_parse() function will actually parse the data and report when + * new frames are found. This funcion should only be called once at + * the beginning of the parsing process, or when the ac3_parse() + * function returns the %AC3P_EVENT_PUSH event. + */ +extern void +ac3p_push_data (ac3_padder * padder, guchar * data, guint size) +{ + padder->in_ptr = data; + padder->remaining = size; +} + + +/** + * ac3p_parse + * @padder The padder structure. + * + * Parses the bytes already pushed into the padder structure (see + * ac3p_push_data()) and returns an event value depending on the + * results of the parsing. + * + * Returns: %AC3P_EVENT_FRAME to indicate that a new AC3 was found and + * padded for IEC958 transmission. This frame can be read inmediatly + * with ac3p_frame(). %AC3P_EVENT_PUSH to indicate that new data from + * the input stream must be pushed into the padder using + * ac3p_push_data(). This function should be called again after + * pushing the data. + */ +extern int +ac3p_parse (ac3_padder * padder) +{ + while (padder->remaining > 0) { + switch (padder->state) { + case AC3P_STATE_SYNC1: + if (*(padder->in_ptr) == 0x0b) { + /* The first sync byte was found. Go to the next state. */ + padder->frame.sync_byte1 = 0x0b; + padder->state = AC3P_STATE_SYNC2; + } + ac3p_in_fw (padder); + break; + + case AC3P_STATE_SYNC2: + if (*(padder->in_ptr) == 0x77) { + /* The second sync byte was seen right after the first. Go to + the next state. */ + padder->frame.sync_byte2 = 0x77; + padder->state = AC3P_STATE_HEADER; + + /* Skip one byte. */ + ac3p_in_fw (padder); + + /* Prepare for reading the header. */ + padder->out_ptr = (guchar *) & (padder->frame.crc1); + /* Discount the 2 sync bytes from the header size. */ + padder->bytes_to_copy = AC3P_AC3_HEADER_SIZE - 2; + } else { + /* The second sync byte was not seen. Go back to the + first state. */ + padder->state = AC3P_STATE_SYNC1; + } + break; + + case AC3P_STATE_HEADER: + if (padder->bytes_to_copy > 0) { + /* Copy one byte. */ + *(padder->out_ptr) = *(padder->in_ptr); + ac3p_in_fw (padder); + ac3p_out_fw (padder); + } else { + int fscod; + + /* The header is ready: */ + + fscod = (padder->frame.code >> 6) & 0x03; + + /* Calculate the frame size. */ + padder->ac3_frame_size = + 2 * frmsizecod_tbl[padder->frame.code & 0x3f].frm_size[fscod]; + + /* Set up the IEC header. */ + if (padder->ac3_frame_size > 0) { + padder->frame.header[4] = IEC61937_DATA_TYPE_AC3; + } else { + /* Don't know what it is, better be careful. */ + padder->state = AC3P_STATE_SYNC1; + break; + } + padder->frame.header[5] = 0x00; + padder->frame.header[6] = (padder->ac3_frame_size * 8) & 0xFF; + padder->frame.header[7] = ((padder->ac3_frame_size * 8) >> 8) & 0xFF; + + /* Prepare for reading the body. */ + padder->bytes_to_copy = padder->ac3_frame_size - AC3P_AC3_HEADER_SIZE; + padder->state = AC3P_STATE_CONTENT; + } + break; + + case AC3P_STATE_CONTENT: + if (padder->bytes_to_copy > 0) { + /* Copy one byte. */ + *(padder->out_ptr) = *(padder->in_ptr); + ac3p_in_fw (padder); + ac3p_out_fw (padder); + } else { + guint16 *ptr, i; + + /* Frame ready. Prepare for output: */ + + /* Zero the non AC3 portion of the padded frame. */ + memset (&(padder->frame.sync_byte1) + padder->ac3_frame_size, 0, + AC3P_IEC_FRAME_SIZE - AC3P_IEC_HEADER_SIZE - + padder->ac3_frame_size); + + /* Fix the byte order in the AC3 portion: */ + ptr = (guint16 *) & (padder->frame.sync_byte1); + i = padder->ac3_frame_size / 2; + while (i > 0) { + *ptr = GUINT16_TO_BE (*ptr); + ptr++; + i--; + } + + /* Start over again. */ + padder->state = AC3P_STATE_SYNC1; + + return AC3P_EVENT_FRAME; + } + break; + } + } + + return AC3P_EVENT_PUSH; +} diff --git a/gst/iec958/ac3_padder.h b/gst/iec958/ac3_padder.h new file mode 100644 index 0000000000..032f41fb25 --- /dev/null +++ b/gst/iec958/ac3_padder.h @@ -0,0 +1,138 @@ +/* GStreamer + * Copyright (C) 2003 Martin Soto + * + * ac3_padder.h: Pad AC3 frames for use with an SPDIF interface. + * + * 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 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef AC3_PADDER_INC +#define AC3_PADDER_INC + +#include + + +/* Size of an IEC958 padded AC3 frame. */ +#define AC3P_IEC_FRAME_SIZE 6144 +/* Size of the IEC958 header. */ +#define AC3P_IEC_HEADER_SIZE 8 +/* Size of the AC3 header. */ +#define AC3P_AC3_HEADER_SIZE 7 + + +/* An IEC958 padded AC3 frame. */ +typedef struct { + /* IEC header. */ + guchar header[AC3P_IEC_HEADER_SIZE]; + + /* Begin of AC3 header. */ + guchar sync_byte1; + guchar sync_byte2; + + guchar crc1[2]; + guchar code; + guchar bsidmod; + guchar acmod; + /* End of AC3 header. */ + + unsigned char data[AC3P_IEC_FRAME_SIZE - AC3P_IEC_HEADER_SIZE + - AC3P_AC3_HEADER_SIZE]; +} ac3p_iec958_burst_frame; + + +/* Possible states for the reading automaton: */ + +/* Searching for sync byte 1. */ +#define AC3P_STATE_SYNC1 1 +/* Searching for sync byte 2. */ +#define AC3P_STATE_SYNC2 2 +/* Reading AC3 header. */ +#define AC3P_STATE_HEADER 3 +/* Reading packet contents.*/ +#define AC3P_STATE_CONTENT 4 + + +/* Events generated by the parse function: */ + +/* The parser needs new data to be pushed. */ +#define AC3P_EVENT_PUSH 1 +/* There is a new padded frame ready to read from the padder structure. */ +#define AC3P_EVENT_FRAME 2 + + +/* The internal state for the padder. */ +typedef struct { + guint state; /* State of the reading automaton. */ + + guchar *in_ptr; /* Input pointer, marking the current + postion in the input buffer. */ + guint remaining; /* The number of bytes remaining in the current + reading buffer. */ + + guchar *out_ptr; /* Output pointer, marking the current + position in the output frame. */ + guint bytes_to_copy; + /* Number of bytes that still must be copied + to the output frame *during this reading + stage*. */ + + guint ac3_frame_size; + /* The size in bytes of the pure AC3 portion + of the current frame. */ + + ac3p_iec958_burst_frame frame; + /* The current output frame. */ +} ac3_padder; + + + +extern void +ac3p_init(ac3_padder *padder); + +extern void +ac3p_push_data(ac3_padder *padder, guchar *data, guint size); + +extern int +ac3p_parse(ac3_padder *padder); + + +/** + * ac3p_frame + * @padder The padder structure. + * + * Returns a pointer to the padded frame contained in the padder. + */ +#define ac3p_frame(padder) ((guint8 *) &((padder)->frame)) + +/** + * ac3p_frame_size + * @padder The padder structure. + * + * Returns the length in bytes of the last read raw AC3 frame. + */ +#define ac3p_frame_size(padder) ((padder)->ac3_frame_size) + +/** + * ac3p_pending + * @padder The padder structure. + * + * Returns a boolean value telling if there are pending material in + * the padder. + */ +#define ac3p_pending(padder) ((padder)->remaining > 0) + + +#endif diff --git a/gst/iec958/ac3iec.c b/gst/iec958/ac3iec.c new file mode 100644 index 0000000000..7707f4d94e --- /dev/null +++ b/gst/iec958/ac3iec.c @@ -0,0 +1,331 @@ +/* GStreamer + * Copyright (C) 2004 Martin Soto + * + * ac3iec.c: Pad AC3 frames into IEC958 frames for the SP/DIF interface. + * + * 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 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "ac3iec.h" + + +GST_DEBUG_CATEGORY_STATIC (ac3iec_debug); +#define GST_CAT_DEFAULT (ac3iec_debug) + + +/* The duration of a single IEC958 frame. */ +#define IEC958_FRAME_DURATION (32 * GST_MSECOND) + + +/* ElementFactory information. */ +static GstElementDetails ac3iec_details = { + "AC3 to IEC958 filter", + "audio/x-ac3", + "Pads AC3 frames into IEC958 frames suitable for a raw SP/DIF interface", + "Martin Soto " +}; + + +/* AC3IEC signals and args */ +enum +{ + LAST_SIGNAL, +}; + +enum +{ + ARG_0, +}; + + +static GstStaticPadTemplate ac3iec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-ac3") + ); + +static GstStaticPadTemplate ac3iec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, +#if 1 + GST_STATIC_CAPS ("audio/x-raw-int, " + "law = (int) 0, " + "endianness = (int) " G_STRINGIFY (G_LITTLE_ENDIAN) ", " + "signed = (boolean) true, " + "width = (int) 16, " + "depth = (int) 16, " "rate = (int) 48000, " "channels = (int) 2") +#endif +#if 0 + GST_STATIC_CAPS ("audio/x-iec958") +#endif + ); + + +static void ac3iec_base_init (gpointer g_class); +static void ac3iec_class_init (AC3IECClass * klass); +static void ac3iec_init (AC3IEC * ac3iec); +static void ac3iec_finalize (GObject * object); + +static void ac3iec_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void ac3iec_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstFlowReturn ac3iec_chain (GstPad * pad, GstBuffer * buf); + +static GstElementStateReturn ac3iec_change_state (GstElement * element); + + +static GstElementClass *parent_class = NULL; + +/* static guint ac3iec_signals[LAST_SIGNAL] = { 0 }; */ + + +GType +ac3iec_get_type (void) +{ + static GType ac3iec_type = 0; + + if (!ac3iec_type) { + static const GTypeInfo ac3iec_info = { + sizeof (AC3IECClass), + ac3iec_base_init, + NULL, + (GClassInitFunc) ac3iec_class_init, + NULL, + NULL, + sizeof (AC3IEC), + 0, + (GInstanceInitFunc) ac3iec_init, + }; + ac3iec_type = g_type_register_static (GST_TYPE_ELEMENT, + "AC3IEC", &ac3iec_info, 0); + + GST_DEBUG_CATEGORY_INIT (ac3iec_debug, "ac3iec", 0, + "AC3 to IEC958 padding element"); + } + return ac3iec_type; +} + + +static void +ac3iec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details (element_class, &ac3iec_details); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ac3iec_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ac3iec_src_template)); +} + + +static void +ac3iec_class_init (AC3IECClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + + gobject_class->set_property = ac3iec_set_property; + gobject_class->get_property = ac3iec_get_property; + gobject_class->finalize = ac3iec_finalize; + + gstelement_class->change_state = ac3iec_change_state; +} + + +static void +ac3iec_init (AC3IEC * ac3iec) +{ + ac3iec->sink = + gst_pad_new_from_template (gst_static_pad_template_get + (&ac3iec_sink_template), "sink"); + gst_element_add_pad (GST_ELEMENT (ac3iec), ac3iec->sink); + gst_pad_set_chain_function (ac3iec->sink, ac3iec_chain); + + ac3iec->src = + gst_pad_new_from_template (gst_static_pad_template_get + (&ac3iec_src_template), "src"); + gst_element_add_pad (GST_ELEMENT (ac3iec), ac3iec->src); + + ac3iec->cur_ts = GST_CLOCK_TIME_NONE; + + ac3iec->padder = g_malloc (sizeof (ac3_padder)); +} + + +static void +ac3iec_finalize (GObject * object) +{ + AC3IEC *ac3iec = AC3IEC (object); + + g_free (ac3iec->padder); +} + + +static void +ac3iec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + AC3IEC *ac3iec; + + /* it's not null if we got it, but it might not be ours */ + ac3iec = AC3IEC (object); + + switch (prop_id) { + default: + break; + } +} + + +static void +ac3iec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + AC3IEC *ac3iec; + + /* it's not null if we got it, but it might not be ours */ + g_return_if_fail (GST_IS_AC3IEC (object)); + + ac3iec = AC3IEC (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstFlowReturn +ac3iec_chain (GstPad * pad, GstBuffer * buf) +{ + GstBuffer *new; + AC3IEC *ac3iec; + int event; + GstFlowReturn ret = GST_FLOW_OK; + + g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + + ac3iec = AC3IEC (gst_pad_get_parent (pad)); + + if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { + /* Whoever tells me why it is necessary to add a frame in order to + get synchronized sound will get a beer from me. */ + ac3iec->cur_ts = GST_BUFFER_TIMESTAMP (buf) + IEC958_FRAME_DURATION; + } + + /* Push the new data into the padder. */ + ac3p_push_data (ac3iec->padder, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + + /* Parse the data. */ + event = ac3p_parse (ac3iec->padder); + while (event != AC3P_EVENT_PUSH) { + if (event == AC3P_EVENT_FRAME) { + /* We have a new frame: */ + + /* Create a new buffer, and copy the frame data into it. */ + new = gst_buffer_new_and_alloc (AC3P_IEC_FRAME_SIZE); + memcpy (GST_BUFFER_DATA (new), ac3p_frame (ac3iec->padder), + AC3P_IEC_FRAME_SIZE); + + /* Set the timestamp. */ + GST_BUFFER_TIMESTAMP (new) = ac3iec->cur_ts; + ac3iec->cur_ts = GST_CLOCK_TIME_NONE; + + GST_LOG_OBJECT (ac3iec, "Pushing IEC958 buffer of size %d", + GST_BUFFER_SIZE (new)); + /* Push the buffer to the source pad. */ + ret = gst_pad_push (ac3iec->src, new); + } + + event = ac3p_parse (ac3iec->padder); + } + + gst_buffer_unref (buf); + + return ret; +} + + +static GstElementStateReturn +ac3iec_change_state (GstElement * element) +{ + AC3IEC *ac3iec; + + g_return_val_if_fail (GST_IS_AC3IEC (element), GST_STATE_FAILURE); + + ac3iec = AC3IEC (element); + + switch (GST_STATE_TRANSITION (element)) { + case GST_STATE_NULL_TO_READY: + break; + case GST_STATE_READY_TO_PAUSED: + ac3p_init (ac3iec->padder); + break; + case GST_STATE_PAUSED_TO_PLAYING: + break; + case GST_STATE_PLAYING_TO_PAUSED: + break; + case GST_STATE_PAUSED_TO_READY: + break; + case GST_STATE_READY_TO_NULL: + break; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) { + return GST_ELEMENT_CLASS (parent_class)->change_state (element); + } + + return GST_STATE_SUCCESS; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "ac3iec958", GST_RANK_NONE, + GST_TYPE_AC3IEC)) { + return FALSE; + } + + return TRUE; +} + + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "iec958", + "Conversion elements to the iec958 SP/DIF format", + plugin_init, VERSION, "LGPL", PACKAGE, "http://seamless.sourceforge.net"); diff --git a/gst/iec958/ac3iec.h b/gst/iec958/ac3iec.h new file mode 100644 index 0000000000..cc91d93cb6 --- /dev/null +++ b/gst/iec958/ac3iec.h @@ -0,0 +1,79 @@ +/* GStreamer + * Copyright (C) 2004 Martin Soto + * + * ac3iec.h: Pad AC3 frames into IEC958 frames for the SP/DIF interface. + * + * 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 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __AC3IEC_H__ +#define __AC3IEC_H__ + +#include + +#include "ac3_padder.h" + +G_BEGIN_DECLS + + +#define GST_TYPE_AC3IEC \ + (ac3iec_get_type()) +#define AC3IEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AC3IEC,AC3IEC)) +#define AC3IEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AC3IEC,AC3IECClass)) +#define GST_IS_AC3IEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AC3IEC)) +#define GST_IS_AC3IEC_CLASS(obj) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AC3IEC)) + + +typedef struct _AC3IEC AC3IEC; +typedef struct _AC3IECClass AC3IECClass; + + +typedef enum { + AC3IEC_OPEN = GST_ELEMENT_FLAG_LAST, + AC3IEC_FLAG_LAST +} Ac3iecFlags; + + +struct _AC3IEC { + GstElement element; + + GstPad *sink; + GstPad *src; + + GstClockTime cur_ts; /* Time stamp for the current + frame. */ + GstClockTime next_ts; /* Time stamp for the next frame. */ + + ac3_padder *padder; /* AC3 to SPDIF padder object. */ +}; + + +struct _AC3IECClass { + GstElementClass parent_class; + + /* Signals */ +}; + + +extern GType ac3iec_get_type (void); + +G_END_DECLS + +#endif /* __AC3IEC_H__ */