diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | gst/cdxaparse/gstcdxaparse.c | 346 | ||||
-rw-r--r-- | gst/cdxaparse/gstcdxaparse.h | 43 |
3 files changed, 238 insertions, 167 deletions
@@ -1,3 +1,19 @@ +2004-05-13 Stephane Loeuillet <stephane.loeuillet@tiscali.fr> + + * ext/mad/gstid3tag.c : move from "Codec/(Dem/M)uxer" to "Codec/(Dem/M)uxer/Audio" + * gst/wavenc/gstwavenc.c : move from "Codec/Encoder/Audio" to "Codec/Muxer/Audio" + + * gst/auparse/gstauparse.c : + - add code (commented for now) to support audio/x-adpcm on src pad + (we have no decoder for those layout yet) + + * gst/cdxaparse/gstcdxaparse.c : + * gst/cdxaparse/gstcdxaparse.h : + - partial rewrite using RiffRead (ripped iain's wavparse code) + + * gst/rtp/gstrtpL16enc.c : typo + * gst/rtp/gstrtpgsmenc.c : typo + 2004-05-13 Benjamin Otte <otte@gnome.org> * configure.ac: diff --git a/gst/cdxaparse/gstcdxaparse.c b/gst/cdxaparse/gstcdxaparse.c index d0029dff..b7b4dc68 100644 --- a/gst/cdxaparse/gstcdxaparse.c +++ b/gst/cdxaparse/gstcdxaparse.c @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ /* GStreamer * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> * <2002> Wim Taymans <wim.taymans@chello.be> @@ -25,27 +26,37 @@ #include <string.h> #include "gstcdxaparse.h" +#include "gst/riff/riff-ids.h" +#include "gst/riff/riff-media.h" -#define MAKE_FOUR_CC(a,b,c,d) ( ((guint32)a) | (((guint32)b)<< 8) | \ - ((guint32)c)<<16 | (((guint32)d)<<24) ) - +static void gst_cdxa_parse_base_init (gpointer g_class); +static void gst_cdxa_parse_class_init (GstCDXAParseClass * klass); +static void gst_cdxa_parse_init (GstCDXAParse * cdxa_parse); -/* RIFF types */ -#define GST_RIFF_TAG_RIFF MAKE_FOUR_CC('R','I','F','F') -#define GST_RIFF_RIFF_CDXA MAKE_FOUR_CC('C','D','X','A') +static GstElementStateReturn gst_cdxa_parse_change_state (GstElement * element); +static void gst_cdxa_parse_loop (GstElement * element); -#define GST_RIFF_TAG_fmt MAKE_FOUR_CC('f','m','t',' ') -#define GST_RIFF_TAG_data MAKE_FOUR_CC('d','a','t','a') +/* elementfactory information */ +static GstElementDetails gst_cdxa_parse_details = +GST_ELEMENT_DETAILS (".dat parser", + "Codec/Parser", + "Parse a .dat file (VCD) into raw mpeg1", + "Wim Taymans <wim.taymans@tvd.be>"); +static GstStaticPadTemplate sink_template_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-cdxa") + ); -/* elementfactory information */ -static GstElementDetails gst_cdxa_parse_details = { - ".dat parser", - "Codec/Parser", - "Parse a .dat file (VCD) into raw mpeg1", - "Wim Taymans <wim.taymans@tvd.be>", -}; +static GstStaticPadTemplate src_template_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpeg, " "systemstream = (boolean) TRUE") + ); /* CDXAParse signals and args */ enum @@ -60,28 +71,6 @@ enum /* FILL ME */ }; -static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-cdxa") - ); - -static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, " "systemstream = (boolean) TRUE, " - "mpegversion = (int) 1") - ); - -static void gst_cdxa_parse_base_init (gpointer g_class); -static void gst_cdxa_parse_class_init (GstCDXAParseClass * klass); -static void gst_cdxa_parse_init (GstCDXAParse * cdxa_parse); - -static void gst_cdxa_parse_loop (GstElement * element); - -static GstElementStateReturn gst_cdxa_parse_change_state (GstElement * element); - - static GstElementClass *parent_class = NULL; /*static guint gst_cdxa_parse_signals[LAST_SIGNAL] = { 0 }; */ @@ -105,34 +94,37 @@ gst_cdxa_parse_get_type (void) }; cdxa_parse_type = - g_type_register_static (GST_TYPE_ELEMENT, "GstCDXAParse", + g_type_register_static (GST_TYPE_RIFF_READ, "GstCDXAParse", &cdxa_parse_info, 0); } return cdxa_parse_type; } + static void gst_cdxa_parse_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + gst_element_class_set_details (element_class, &gst_cdxa_parse_details); + + /* register src pads */ gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_templ)); + gst_static_pad_template_get (&sink_template_factory)); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_templ)); - gst_element_class_set_details (element_class, &gst_cdxa_parse_details); + gst_static_pad_template_get (&src_template_factory)); } static void gst_cdxa_parse_class_init (GstCDXAParseClass * klass) { - GObjectClass *gobject_class; GstElementClass *gstelement_class; + GObjectClass *object_class; - gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + object_class = (GObjectClass *) klass; - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + parent_class = g_type_class_ref (GST_TYPE_RIFF_READ); gstelement_class->change_state = gst_cdxa_parse_change_state; } @@ -140,144 +132,181 @@ gst_cdxa_parse_class_init (GstCDXAParseClass * klass) static void gst_cdxa_parse_init (GstCDXAParse * cdxa_parse) { - GST_FLAG_SET (cdxa_parse, GST_ELEMENT_EVENT_AWARE); - + /* sink */ cdxa_parse->sinkpad = - gst_pad_new_from_template (gst_static_pad_template_get (&sink_templ), - "sink"); + gst_pad_new_from_template (gst_static_pad_template_get + (&sink_template_factory), "sink"); gst_element_add_pad (GST_ELEMENT (cdxa_parse), cdxa_parse->sinkpad); + GST_RIFF_READ (cdxa_parse)->sinkpad = cdxa_parse->sinkpad; + + + gst_element_set_loop_function (GST_ELEMENT (cdxa_parse), gst_cdxa_parse_loop); + cdxa_parse->srcpad = - gst_pad_new_from_template (gst_static_pad_template_get (&src_templ), - "src"); + gst_pad_new_from_template (gst_static_pad_template_get + (&src_template_factory), "src"); gst_element_add_pad (GST_ELEMENT (cdxa_parse), cdxa_parse->srcpad); - gst_element_set_loop_function (GST_ELEMENT (cdxa_parse), gst_cdxa_parse_loop); + cdxa_parse->state = GST_CDXA_PARSE_START; + cdxa_parse->seek_pending = FALSE; + cdxa_parse->seek_offset = 0; } static gboolean -gst_cdxa_parse_handle_event (GstCDXAParse * cdxa_parse) +gst_cdxa_parse_stream_init (GstCDXAParse * cdxa_parse) { - guint32 remaining; - GstEvent *event; - GstEventType type; + GstRiffRead *riff = GST_RIFF_READ (cdxa_parse); + guint32 doctype; - gst_bytestream_get_status (cdxa_parse->bs, &remaining, &event); + if (!gst_riff_read_header (riff, &doctype)) + return FALSE; - type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; + if (doctype != GST_RIFF_RIFF_CDXA) { + GST_ELEMENT_ERROR (cdxa_parse, STREAM, WRONG_TYPE, (NULL), (NULL)); + return FALSE; + } - switch (type) { - case GST_EVENT_EOS: - gst_pad_event_default (cdxa_parse->sinkpad, event); - break; - case GST_EVENT_SEEK: - g_warning ("seek event\n"); - break; - case GST_EVENT_FLUSH: - g_warning ("flush event\n"); - break; - case GST_EVENT_DISCONTINUOUS: - g_warning ("discont event\n"); + return TRUE; +} + +/* Read 'fmt ' header */ +static gboolean +gst_cdxa_parse_fmt (GstCDXAParse * cdxa_parse) +{ + GstRiffRead *riff = GST_RIFF_READ (cdxa_parse); + gst_riff_strf_auds *header; + + if (!gst_riff_read_strf_auds (riff, &header)) { + g_warning ("Not fmt"); + return FALSE; + } + + /* As we don't know what is in this fmt field, we do nothing */ + + return TRUE; +} + +static gboolean +gst_cdxa_parse_other (GstCDXAParse * cdxa_parse) +{ + GstRiffRead *riff = GST_RIFF_READ (cdxa_parse); + guint32 tag, length; + + /* Fixme, need to handle a seek...can you seek in cdxa? */ + + if (!gst_riff_peek_head (riff, &tag, &length, NULL)) { + return FALSE; + } + + switch (tag) { + case GST_RIFF_TAG_data: + gst_bytestream_flush (riff->bs, 8); + + cdxa_parse->state = GST_CDXA_PARSE_DATA; + cdxa_parse->dataleft = (guint64) length; break; + default: - g_warning ("unhandled event %d\n", type); + gst_riff_read_skip (riff); break; } return TRUE; } -/* +#define MAX_BUFFER_SIZE 4096 + +static void +gst_cdxa_parse_loop (GstElement * element) +{ + GstCDXAParse *cdxa_parse = GST_CDXA_PARSE (element); + GstRiffRead *riff = GST_RIFF_READ (cdxa_parse); -CDXA starts with the following header: - -! RIFF:4 ! size:4 ! "CDXA" ! "fmt " ! size:4 ! (size+1)&~1 bytes of crap ! -! "data" ! data_size:4 ! (data_size/2352) sectors... + if (cdxa_parse->state == GST_CDXA_PARSE_DATA) { + if (cdxa_parse->dataleft > 0) { + guint32 got_bytes, desired; + GstBuffer *buf, *outbuf; -*/ + desired = GST_CDXA_SECTOR_SIZE; -typedef struct -{ - gchar RIFF_tag[4]; - guint32 riff_size; - gchar CDXA_tag[4]; - gchar fmt_tag[4]; - guint32 fmt_size; -} -CDXAParseHeader; + buf = gst_riff_read_element_data (riff, desired, &got_bytes); /* -A sectors is 2352 bytes long and is composed of: + +A sector is 2352 bytes long and is composed of: ! sync ! header ! subheader ! data ... ! edc ! ! 12 bytes ! 4 bytes ! 8 bytes ! 2324 bytes ! 4 bytes ! !-------------------------------------------------------! We parse the data out of it and send it to the srcpad. + +sync : 00 FF FF FF FF FF FF FF FF FF FF 00 +header : hour minute second mode +sub-header : track channel sub_mode coding repeat (4 bytes) +edc : checksum + */ -static void -gst_cdxa_parse_loop (GstElement * element) -{ - GstCDXAParse *cdxa_parse; - CDXAParseHeader *header; - guint8 *headerdata; - - g_return_if_fail (element != NULL); - g_return_if_fail (GST_IS_CDXA_PARSE (element)); - - cdxa_parse = GST_CDXA_PARSE (element); - - if (cdxa_parse->state == CDXA_PARSE_HEADER) { - guint32 fmt_size; - guint8 *buf; - guint32 got_bytes; - - got_bytes = gst_bytestream_peek_bytes (cdxa_parse->bs, &headerdata, 20); - header = (CDXAParseHeader *) headerdata; - if (got_bytes < 20) - return; - - cdxa_parse->riff_size = GUINT32_FROM_LE (header->riff_size); - fmt_size = (GUINT32_FROM_LE (header->fmt_size) + 1) & ~1; - - /* flush the header + fmt_size bytes + 4 bytes "data" */ - if (!gst_bytestream_flush (cdxa_parse->bs, 20 + fmt_size + 4)) - return; - - /* get the data size */ - got_bytes = - gst_bytestream_peek_bytes (cdxa_parse->bs, (guint8 **) & buf, 4); - if (got_bytes < 4) - return; - cdxa_parse->data_size = GST_READ_UINT32_LE (buf); - - /* flush the data size */ - if (!gst_bytestream_flush (cdxa_parse->bs, 4)) - return; - - if (cdxa_parse->data_size % CDXA_SECTOR_SIZE) - g_warning ("cdxa_parse: size not multiple of %d bytes", CDXA_SECTOR_SIZE); - - cdxa_parse->sectors = cdxa_parse->data_size / CDXA_SECTOR_SIZE; - - cdxa_parse->state = CDXA_PARSE_DATA; - } else { - GstBuffer *buf; - GstBuffer *outbuf; - guint32 got_bytes; - - got_bytes = gst_bytestream_read (cdxa_parse->bs, &buf, CDXA_SECTOR_SIZE); - if (got_bytes < CDXA_SECTOR_SIZE) { - gst_cdxa_parse_handle_event (cdxa_parse); - return; +/* + if (got_bytes < GST_CDXA_SECTOR_SIZE) { + gst_cdxa_parse_handle_event (cdxa_parse); + return; + } +*/ + + /* Extract time from CDXA header */ +/* printf( "%02u:%02u:%02u\n", (unsigned char) *(GST_BUFFER_DATA(buf)+12), (unsigned char) *(GST_BUFFER_DATA(buf)+13), (unsigned char) *(GST_BUFFER_DATA(buf)+14) );*/ + + /* Jump CDXA headers, only keep data */ + outbuf = gst_buffer_create_sub (buf, 24, GST_CDXA_DATA_SIZE); + gst_buffer_unref (buf); + + gst_pad_push (cdxa_parse->srcpad, GST_DATA (outbuf)); + + cdxa_parse->byteoffset += got_bytes; + if (got_bytes < cdxa_parse->dataleft) { + cdxa_parse->dataleft -= got_bytes; + return; + } else { + cdxa_parse->dataleft = 0; + cdxa_parse->state = GST_CDXA_PARSE_OTHER; + } + } else { + cdxa_parse->state = GST_CDXA_PARSE_OTHER; } + } + + switch (cdxa_parse->state) { + case GST_CDXA_PARSE_START: + if (!gst_cdxa_parse_stream_init (cdxa_parse)) { + return; + } + + cdxa_parse->state = GST_CDXA_PARSE_FMT; + /* fall-through */ + + case GST_CDXA_PARSE_FMT: + if (!gst_cdxa_parse_fmt (cdxa_parse)) { + return; + } + + cdxa_parse->state = GST_CDXA_PARSE_OTHER; + /* fall-through */ + + case GST_CDXA_PARSE_OTHER: + if (!gst_cdxa_parse_other (cdxa_parse)) { + return; + } + + break; - outbuf = gst_buffer_create_sub (buf, 24, CDXA_DATA_SIZE); - gst_buffer_unref (buf); + case GST_CDXA_PARSE_DATA: - gst_pad_push (cdxa_parse->srcpad, GST_DATA (outbuf)); + default: + g_assert_not_reached (); } } @@ -289,24 +318,31 @@ gst_cdxa_parse_change_state (GstElement * element) switch (GST_STATE_TRANSITION (element)) { case GST_STATE_NULL_TO_READY: break; + case GST_STATE_READY_TO_PAUSED: - cdxa_parse->state = CDXA_PARSE_HEADER; - cdxa_parse->bs = gst_bytestream_new (cdxa_parse->sinkpad); + cdxa_parse->state = GST_CDXA_PARSE_START; break; + case GST_STATE_PAUSED_TO_PLAYING: break; + case GST_STATE_PLAYING_TO_PAUSED: break; + case GST_STATE_PAUSED_TO_READY: - gst_bytestream_destroy (cdxa_parse->bs); + cdxa_parse->state = GST_CDXA_PARSE_START; + + + cdxa_parse->seek_pending = FALSE; + cdxa_parse->seek_offset = 0; break; + case GST_STATE_READY_TO_NULL: break; - default: - break; } - parent_class->change_state (element); + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element); return GST_STATE_SUCCESS; } @@ -314,14 +350,12 @@ gst_cdxa_parse_change_state (GstElement * element) static gboolean plugin_init (GstPlugin * plugin) { - if (!gst_library_load ("gstbytestream")) - return FALSE; - - if (!gst_element_register (plugin, "cdxaparse", GST_RANK_SECONDARY, - GST_TYPE_CDXA_PARSE)) + if (!gst_library_load ("riff")) { return FALSE; + } - return TRUE; + return gst_element_register (plugin, "cdxaparse", GST_RANK_SECONDARY, + GST_TYPE_CDXA_PARSE); } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, diff --git a/gst/cdxaparse/gstcdxaparse.h b/gst/cdxaparse/gstcdxaparse.h index 32af5527..4dc1236e 100644 --- a/gst/cdxaparse/gstcdxaparse.h +++ b/gst/cdxaparse/gstcdxaparse.h @@ -23,7 +23,8 @@ #define __GST_CDXA_PARSE_H__ #include <gst/gst.h> -#include <gst/bytestream/bytestream.h> +#include "gst/riff/riff-ids.h" +#include "gst/riff/riff-read.h" #ifdef __cplusplus extern "C" { @@ -40,31 +41,49 @@ extern "C" { #define GST_IS_CDXA_PARSE_CLASS(obj) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CDXA_PARSE)) -#define CDXA_SECTOR_SIZE 2352 -#define CDXA_DATA_SIZE 2324 +#define GST_CDXA_SECTOR_SIZE 2352 +#define GST_CDXA_DATA_SIZE 2324 -typedef enum -{ - CDXA_PARSE_HEADER, - CDXA_PARSE_DATA, +typedef enum { + GST_CDXA_PARSE_START, + GST_CDXA_PARSE_FMT, + GST_CDXA_PARSE_OTHER, + GST_CDXA_PARSE_DATA, } GstCDXAParseState; typedef struct _GstCDXAParse GstCDXAParse; typedef struct _GstCDXAParseClass GstCDXAParseClass; struct _GstCDXAParse { - GstElement element; + GstRiffRead parent; /* pads */ - GstPad *sinkpad, *srcpad; - - GstByteStream *bs; + GstPad *sinkpad,*srcpad; + /* CDXA decoding state */ GstCDXAParseState state; + /* useful CDXA data guint32 riff_size; guint32 data_size; guint32 sectors; + +#define CDXA_SUB_MODE_EOF(c) ((c&0x80)>>7) +#define CDXA_SUB_MODE_RT(c) ((c&0x40)>>6) +#define CDXA_SUB_MODE_FORM(c) ((c&0x20)>>5) +#define CDXA_SUB_MODE_TRIGGER(c)((c&0x10)>>4) +#define CDXA_SUB_MODE_DATA(c) ((c&0x08)>>3) +#define CDXA_SUB_MODE_VIDEO(c) ((c&0x04)>>2) +#define CDXA_SUB_MODE_AUDIO(c) ((c&0x02)>>1) +#define CDXA_SUB_MODE_EOR(c) ((c&0x01) ) + +*/ + + guint64 dataleft; + int byteoffset; + + gboolean seek_pending; + guint64 seek_offset; }; struct _GstCDXAParseClass { @@ -77,4 +96,6 @@ GType gst_cdxa_parse_get_type (void); } #endif /* __cplusplus */ + #endif /* __GST_CDXA_PARSE_H__ */ + |