summaryrefslogtreecommitdiff
path: root/ext/dirac/gstdiracdec.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ext/dirac/gstdiracdec.cc')
-rw-r--r--ext/dirac/gstdiracdec.cc287
1 files changed, 213 insertions, 74 deletions
diff --git a/ext/dirac/gstdiracdec.cc b/ext/dirac/gstdiracdec.cc
index 5a767c455..6a9c3abf6 100644
--- a/ext/dirac/gstdiracdec.cc
+++ b/ext/dirac/gstdiracdec.cc
@@ -1,5 +1,6 @@
/* GStreamer
* Copyright (C) 2004 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2004 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -22,54 +23,19 @@
#include "config.h"
#endif
-#include <gst/gst.h>
-#include <gst/video/video.h>
-
-#include <libdirac_decoder/seq_decompress.h>
-#include <libdirac_common/pic_io.h>
-
-#define GST_TYPE_DIRACDEC \
- (gst_diracdec_get_type())
-#define GST_DIRACDEC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRACDEC,GstDiracDec))
-#define GST_DIRACDEC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRACDEC,GstDiracDec))
-#define GST_IS_DIRACDEC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRACDEC))
-#define GST_IS_DIRACDEC_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRACDEC))
-
-typedef struct _GstDiracDec GstDiracDec;
-typedef struct _GstDiracDecClass GstDiracDecClass;
-
-struct _GstDiracDec
-{
- GstElement element;
-
- /* pads */
- GstPad *sinkpad, *srcpad;
-
- SequenceDecompressor *decompress;
-
- std::istream * input_stream;
- PicOutput *output_image;
-
-};
+#include <string.h>
-struct _GstDiracDecClass
-{
- GstElementClass parent_class;
-};
-
-GType gst_diracdec_get_type (void);
+#include <gst/video/video.h>
+#include "gstdiracdec.h"
/* elementfactory information */
-GstElementDetails gst_diracdec_details = {
+static GstElementDetails gst_diracdec_details = {
"Dirac stream decoder",
"Codec/Decoder/Video",
"Decode DIRAC streams",
- "David Schleef <ds@schleef.org>",
+ "David Schleef <ds@schleef.org>\n"
+ "Ronald Bultje <rbultje@ronald.bitfreak.net>",
};
GST_DEBUG_CATEGORY (diracdec_debug);
@@ -90,9 +56,10 @@ enum
static void gst_diracdec_base_init (gpointer g_class);
static void gst_diracdec_class_init (GstDiracDec * klass);
static void gst_diracdec_init (GstDiracDec * diracdec);
+static void gst_diracdec_dispose (GObject * object);
-static void gst_diracdec_chain (GstPad * pad, GstData * _data);
-static GstPadLinkReturn gst_diracdec_link (GstPad * pad, const GstCaps * caps);
+static void gst_diracdec_chain (GstPad * pad, GstData * data);
+static GstElementStateReturn gst_diracdec_change_state (GstElement * element);
static GstElementClass *parent_class = NULL;
@@ -120,6 +87,7 @@ gst_diracdec_get_type (void)
g_type_register_static (GST_TYPE_ELEMENT, "GstDiracDec", &diracdec_info,
(GTypeFlags) 0);
}
+
return diracdec_type;
}
@@ -127,16 +95,15 @@ static GstStaticPadTemplate gst_diracdec_src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420"))
+ /* FIXME: 444 (planar? packed?), 411 (Y41B? Y41P?) */
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, Y800 }"))
);
static GstStaticPadTemplate gst_diracdec_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("image/dirac, "
- "width = (int) [ 16, 4096 ], "
- "height = (int) [ 16, 4096 ], " "framerate = (double) [ 1, MAX ]")
+ GST_STATIC_CAPS ("video/x-dirac")
);
static void
@@ -154,29 +121,34 @@ gst_diracdec_base_init (gpointer g_class)
static void
gst_diracdec_class_init (GstDiracDec * klass)
{
- GstElementClass *gstelement_class;
-
- gstelement_class = (GstElementClass *) klass;
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
parent_class = GST_ELEMENT_CLASS (g_type_class_ref (GST_TYPE_ELEMENT));
+ gobject_class->dispose = gst_diracdec_dispose;
+ element_class->change_state = gst_diracdec_change_state;
+
GST_DEBUG_CATEGORY_INIT (diracdec_debug, "diracdec", 0, "DIRAC decoder");
}
static void
-gst_diracdec_init (GstDiracDec * diracdec)
+gst_diracdec_dispose (GObject * object)
{
- SeqParams params;
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+static void
+gst_diracdec_init (GstDiracDec * diracdec)
+{
GST_DEBUG ("gst_diracdec_init: initializing");
/* create the sink and src pads */
diracdec->sinkpad =
gst_pad_new_from_template (gst_static_pad_template_get
(&gst_diracdec_sink_pad_template), "sink");
- gst_element_add_pad (GST_ELEMENT (diracdec), diracdec->sinkpad);
gst_pad_set_chain_function (diracdec->sinkpad, gst_diracdec_chain);
- gst_pad_set_link_function (diracdec->sinkpad, gst_diracdec_link);
+ gst_element_add_pad (GST_ELEMENT (diracdec), diracdec->sinkpad);
diracdec->srcpad =
gst_pad_new_from_template (gst_static_pad_template_get
@@ -184,37 +156,204 @@ gst_diracdec_init (GstDiracDec * diracdec)
gst_pad_use_explicit_caps (diracdec->srcpad);
gst_element_add_pad (GST_ELEMENT (diracdec), diracdec->srcpad);
- //diracdec->input_stream = new std::istream ();
- diracdec->input_stream = NULL;
- diracdec->decompress =
- new SequenceDecompressor (diracdec->input_stream, FALSE);
- diracdec->output_image = new PicOutput ("moo", params, (bool) FALSE);
+ /* no capsnego done yet */
+ diracdec->width = -1;
+ diracdec->height = -1;
+ diracdec->fps = 0;
+ diracdec->fcc = 0;
}
-static GstPadLinkReturn
-gst_diracdec_link (GstPad * pad, const GstCaps * caps)
+static guint32
+gst_diracdec_chroma_to_fourcc (dirac_chroma_t chroma)
{
- //GstDiracDec *diracdec = GST_DIRACDEC (gst_pad_get_parent (pad));
- GstStructure *structure;
+ guint32 fourcc = 0;
+
+ switch (chroma) {
+ case Yonly:
+ fourcc = GST_MAKE_FOURCC ('Y', '8', '0', '0');
+ break;
+ case format422:
+ fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
+ break;
+ /* planar? */
+ case format420:
+ case format444:
+ case format411:
+ default:
+ break;
+ }
- //GstCaps *srccaps;
+ return fourcc;
+}
- structure = gst_caps_get_structure (caps, 0);
+static gboolean
+gst_diracdec_link (GstDiracDec * diracdec,
+ gint width, gint height, gdouble fps, guint32 fourcc)
+{
+ GstCaps *caps;
+
+ if (width == diracdec->width &&
+ height == diracdec->height &&
+ fps == diracdec->fps && fourcc == diracdec->fcc) {
+ return TRUE;
+ }
- return GST_PAD_LINK_OK;
+ if (!fourcc) {
+ g_warning ("Chroma not supported\n");
+ return FALSE;
+ }
+
+ caps = gst_caps_new_simple ("video/x-raw-yuv",
+ "width", G_TYPE_INT, width,
+ "height", G_TYPE_INT, height,
+ "format", GST_TYPE_FOURCC, fourcc, "framerate", G_TYPE_DOUBLE, fps, NULL);
+
+ if (gst_pad_set_explicit_caps (diracdec->srcpad, caps)) {
+ diracdec->width = width;
+ diracdec->height = height;
+ switch (fourcc) {
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+ diracdec->size = width * height * 2;
+ break;
+ case GST_MAKE_FOURCC ('Y', '8', '0', '0'):
+ diracdec->size = width * height;
+ break;
+ }
+ diracdec->fcc = fourcc;
+ diracdec->fps = fps;
+
+ return TRUE;
+ }
+
+ return FALSE;
}
static void
gst_diracdec_chain (GstPad * pad, GstData * _data)
{
- GstBuffer *buf = GST_BUFFER (_data);
- GstDiracDec *diracdec;
-
- g_return_if_fail (pad != NULL);
- g_return_if_fail (GST_IS_PAD (pad));
- g_return_if_fail (buf != NULL);
+ GstDiracDec *diracdec = GST_DIRACDEC (gst_pad_get_parent (pad));
+ GstBuffer *buf = GST_BUFFER (_data), *out;
+ gboolean c = TRUE;
+
+ /* get state and do something */
+ while (c) {
+ switch (dirac_parse (diracdec->decoder)) {
+ case STATE_BUFFER:
+ if (buf) {
+ /* provide data to decoder */
+ dirac_buffer (diracdec->decoder, GST_BUFFER_DATA (buf),
+ GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf));
+ gst_buffer_unref (buf);
+ buf = NULL;
+ } else {
+ /* need more data */
+ c = FALSE;
+ }
+ break;
+
+ case STATE_SEQUENCE:{
+ guint8 *buf[3];
+
+ /* start-of-sequence - allocate buffer */
+ if (!gst_diracdec_link (diracdec,
+ diracdec->decoder->seq_params.width,
+ diracdec->decoder->seq_params.height,
+ gst_diracdec_chroma_to_fourcc (diracdec->decoder->seq_params.
+ chroma), diracdec->decoder->seq_params.frame_rate)) {
+ GST_ELEMENT_ERROR (diracdec, CORE, NEGOTIATION, (NULL),
+ ("Failed to set caps to %dx%d @ %d fps (format=" GST_FOURCC_FORMAT
+ "/%d)", diracdec->decoder->seq_params.width,
+ diracdec->decoder->seq_params.height,
+ diracdec->decoder->seq_params.frame_rate,
+ gst_diracdec_chroma_to_fourcc (diracdec->decoder->seq_params.
+ chroma), diracdec->decoder->seq_params.chroma));
+ c = FALSE;
+ break;
+ }
+
+ g_free (diracdec->decoder->fbuf->buf[0]);
+ g_free (diracdec->decoder->fbuf->buf[1]);
+ g_free (diracdec->decoder->fbuf->buf[2]);
+ buf[0] = (guchar *) g_malloc (diracdec->decoder->seq_params.width *
+ diracdec->decoder->seq_params.height);
+ if (diracdec->decoder->seq_params.chroma != Yonly) {
+ buf[1] =
+ (guchar *) g_malloc (diracdec->decoder->seq_params.chroma_width *
+ diracdec->decoder->seq_params.chroma_height);
+ buf[2] =
+ (guchar *) g_malloc (diracdec->decoder->seq_params.chroma_width *
+ diracdec->decoder->seq_params.chroma_height);
+ }
+ dirac_set_buf (diracdec->decoder, buf, NULL);
+ break;
+ }
+
+ case STATE_SEQUENCE_END:
+ /* end-of-sequence - free buffer */
+ g_free (diracdec->decoder->fbuf->buf[0]);
+ diracdec->decoder->fbuf->buf[0] = NULL;
+ g_free (diracdec->decoder->fbuf->buf[1]);
+ diracdec->decoder->fbuf->buf[1] = NULL;
+ g_free (diracdec->decoder->fbuf->buf[2]);
+ diracdec->decoder->fbuf->buf[2] = NULL;
+ break;
+
+ case STATE_PICTURE_START:
+ /* start of one picture */
+ break;
+
+ case STATE_PICTURE_AVAIL:
+ /* one picture is decoded */
+ out = gst_pad_alloc_buffer (diracdec->srcpad, 0, diracdec->size);
+ memcpy (GST_BUFFER_DATA (out), diracdec->decoder->fbuf->buf[0],
+ diracdec->width * diracdec->height);
+ if (diracdec->fcc != GST_MAKE_FOURCC ('Y', '8', '0', '0')) {
+ memcpy (GST_BUFFER_DATA (out) + (diracdec->width *
+ diracdec->height), diracdec->decoder->fbuf->buf[1],
+ diracdec->decoder->seq_params.chroma_width *
+ diracdec->decoder->seq_params.chroma_height);
+ memcpy (GST_BUFFER_DATA (out) +
+ (diracdec->decoder->seq_params.chroma_width *
+ diracdec->decoder->seq_params.chroma_height) +
+ (diracdec->width * diracdec->height),
+ diracdec->decoder->fbuf->buf[2],
+ diracdec->decoder->seq_params.chroma_width *
+ diracdec->decoder->seq_params.chroma_height);
+ }
+ GST_BUFFER_TIMESTAMP (out) = (guint64) (GST_SECOND *
+ diracdec->decoder->frame_params.fnum / diracdec->fps);
+ GST_BUFFER_DURATION (out) = (guint64) (GST_SECOND / diracdec->fps);
+ gst_pad_push (diracdec->srcpad, GST_DATA (out));
+ break;
+
+ case STATE_INVALID:
+ default:
+ GST_ELEMENT_ERROR (diracdec, LIBRARY, TOO_LAZY, (NULL), (NULL));
+ c = FALSE;
+ break;
+ }
+ }
+}
- diracdec = GST_DIRACDEC (GST_OBJECT_PARENT (pad));
+static GstElementStateReturn
+gst_diracdec_change_state (GstElement * element)
+{
+ GstDiracDec *diracdec = GST_DIRACDEC (element);
+
+ switch (GST_STATE_TRANSITION (element)) {
+ case GST_STATE_NULL_TO_READY:
+ if (!(diracdec->decoder = dirac_decoder_init (0)))
+ return GST_STATE_FAILURE;
+ break;
+ case GST_STATE_READY_TO_NULL:
+ dirac_decoder_close (diracdec->decoder);
+ diracdec->width = diracdec->height = -1;
+ diracdec->fps = 0.;
+ diracdec->fcc = 0;
+ break;
+ default:
+ break;
+ }
- gst_buffer_unref (buf);
+ return parent_class->change_state (element);
}