summaryrefslogtreecommitdiffstats
path: root/ext/xvid/gstxviddec.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/xvid/gstxviddec.c')
-rw-r--r--ext/xvid/gstxviddec.c260
1 files changed, 129 insertions, 131 deletions
diff --git a/ext/xvid/gstxviddec.c b/ext/xvid/gstxviddec.c
index 84af838d..37abbed5 100644
--- a/ext/xvid/gstxviddec.c
+++ b/ext/xvid/gstxviddec.c
@@ -22,14 +22,16 @@
#endif
#include <string.h>
-#include "gstxviddec.h"
+#include <xvid.h>
+
#include <gst/video/video.h>
+#include "gstxviddec.h"
/* elementfactory information */
GstElementDetails gst_xviddec_details = {
"Xvid decoder",
"Codec/Video/Decoder",
- "Xvid decoder based on xviddecore",
+ "Xvid decoder based on xvidcore",
"Ronald Bultje <rbultje@ronald.bitfreak.net>",
};
@@ -53,7 +55,11 @@ GST_STATIC_PAD_TEMPLATE (
GST_PAD_ALWAYS,
GST_STATIC_CAPS (
GST_VIDEO_YUV_PAD_TEMPLATE_CAPS ("{ I420, YUY2, YV12, YVYU, UYVY }") "; "
- GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_24_32 "; "
+ RGB_24_32_STATIC_CAPS (32, 0x00ff0000, 0x0000ff00, 0x000000ff) "; "
+ RGB_24_32_STATIC_CAPS (32, 0xff000000, 0x00ff0000, 0x0000ff00) "; "
+ RGB_24_32_STATIC_CAPS (32, 0x0000ff00, 0x00ff0000, 0xff000000) "; "
+ RGB_24_32_STATIC_CAPS (32, 0x000000ff, 0x0000ff00, 0x00ff0000) "; "
+ RGB_24_32_STATIC_CAPS (24, 0x0000ff, 0x00ff00, 0xff0000) "; "
GST_VIDEO_RGB_PAD_TEMPLATE_CAPS_15_16
)
);
@@ -70,15 +76,20 @@ enum {
/* FILL ME */
};
-static void gst_xviddec_base_init (gpointer g_class);
-static void gst_xviddec_class_init (GstXvidDecClass *klass);
-static void gst_xviddec_init (GstXvidDec *xviddec);
-static void gst_xviddec_dispose (GObject *object);
-static void gst_xviddec_chain (GstPad *pad,
- GstData *data);
-static GstPadLinkReturn gst_xviddec_link (GstPad *pad,
- const GstCaps *vscapslist);
-static GstPadLinkReturn gst_xviddec_negotiate (GstXvidDec *xviddec);
+static void gst_xviddec_base_init (gpointer g_class);
+static void gst_xviddec_class_init (GstXvidDecClass *klass);
+static void gst_xviddec_init (GstXvidDec *xviddec);
+static void gst_xviddec_chain (GstPad *pad,
+ GstData *data);
+static GstPadLinkReturn
+ gst_xviddec_sink_link (GstPad *pad,
+ const GstCaps *vscapslist);
+static GstPadLinkReturn
+ gst_xviddec_src_link (GstPad *pad,
+ const GstCaps *vscapslist);
+static GstElementStateReturn
+ gst_xviddec_change_state (GstElement *element);
+
static GstElementClass *parent_class = NULL;
/* static guint gst_xviddec_signals[LAST_SIGNAL] = { 0 }; */
@@ -125,19 +136,19 @@ gst_xviddec_base_init (gpointer g_class)
static void
gst_xviddec_class_init (GstXvidDecClass *klass)
{
- GObjectClass *gobject_class = (GObjectClass *) klass;
-
- gst_xvid_init();
+ GstElementClass *gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_ref(GST_TYPE_ELEMENT);
- gobject_class->dispose = gst_xviddec_dispose;
+ gstelement_class->change_state = gst_xviddec_change_state;
}
static void
gst_xviddec_init (GstXvidDec *xviddec)
{
+ gst_xvid_init();
+
/* create the sink pad */
xviddec->sinkpad = gst_pad_new_from_template(
gst_static_pad_template_get (&sink_template),
@@ -145,7 +156,7 @@ gst_xviddec_init (GstXvidDec *xviddec)
gst_element_add_pad(GST_ELEMENT(xviddec), xviddec->sinkpad);
gst_pad_set_chain_function(xviddec->sinkpad, gst_xviddec_chain);
- gst_pad_set_link_function(xviddec->sinkpad, gst_xviddec_link);
+ gst_pad_set_link_function(xviddec->sinkpad, gst_xviddec_sink_link);
/* create the src pad */
xviddec->srcpad = gst_pad_new_from_template(
@@ -153,7 +164,9 @@ gst_xviddec_init (GstXvidDec *xviddec)
"src");
gst_element_add_pad(GST_ELEMENT(xviddec), xviddec->srcpad);
- /* bitrate, etc. */
+ gst_pad_set_link_function(xviddec->srcpad, gst_xviddec_src_link);
+
+ /* size, etc. */
xviddec->width = xviddec->height = xviddec->csp = -1;
/* set xvid handle to NULL */
@@ -173,16 +186,17 @@ gst_xviddec_unset (GstXvidDec *xviddec)
static gboolean
gst_xviddec_setup (GstXvidDec *xviddec)
{
- XVID_DEC_PARAM xdec;
+ xvid_dec_create_t xdec;
int ret;
/* initialise parameters, see xvid documentation */
- memset(&xdec, 0, sizeof(XVID_DEC_PARAM));
+ gst_xvid_init_struct (xdec);
xdec.width = xviddec->width;
xdec.height = xviddec->height;
+ xdec.handle = NULL;
if ((ret = xvid_decore(NULL, XVID_DEC_CREATE,
- &xdec, NULL)) != XVID_ERR_OK) {
+ &xdec, NULL)) < 0) {
gst_element_error(GST_ELEMENT(xviddec),
"Setting parameters %dx%d@%d failed: %s (%d)",
xviddec->width, xviddec->height, xviddec->csp,
@@ -197,60 +211,59 @@ gst_xviddec_setup (GstXvidDec *xviddec)
static void
-gst_xviddec_dispose (GObject *object)
-{
- GstXvidDec *xviddec = GST_XVIDDEC(object);
-
- gst_xviddec_unset(xviddec);
-}
-
-
-static void
gst_xviddec_chain (GstPad *pad,
GstData *_data)
{
GstBuffer *buf = GST_BUFFER (_data);
- GstXvidDec *xviddec;
+ GstXvidDec *xviddec = GST_XVIDDEC(GST_OBJECT_PARENT(pad));
GstBuffer *outbuf;
- XVID_DEC_FRAME xframe;
+ xvid_dec_frame_t xframe;
int ret;
g_return_if_fail(pad != NULL);
g_return_if_fail(GST_IS_PAD(pad));
- g_return_if_fail(buf != NULL);
-
- xviddec = GST_XVIDDEC(GST_OBJECT_PARENT(pad));
if (!xviddec->handle) {
- if (!gst_xviddec_negotiate(xviddec)) {
- gst_element_error(GST_ELEMENT(xviddec),
- "No format set - aborting");
- gst_buffer_unref(buf);
- return;
- }
+ gst_element_error(GST_ELEMENT(xviddec),
+ "No format set - aborting");
+ gst_buffer_unref(buf);
+ return;
}
outbuf = gst_buffer_new_and_alloc(xviddec->width *
xviddec->height *
xviddec->bpp / 8);
GST_BUFFER_TIMESTAMP(outbuf) = GST_BUFFER_TIMESTAMP(buf);
+ GST_BUFFER_DURATION(outbuf) = GST_BUFFER_DURATION(buf);
GST_BUFFER_SIZE(outbuf) = xviddec->width *
xviddec->height *
xviddec->bpp / 8;
- /* encode and so ... */
+ /* decode and so ... */
+ gst_xvid_init_struct (xframe);
+ xframe.general = 0;
xframe.bitstream = (void *) GST_BUFFER_DATA(buf);
- xframe.image = (void *) GST_BUFFER_DATA(outbuf);
xframe.length = GST_BUFFER_SIZE(buf);
- xframe.stride = 0; /*xviddec->width * xviddec->bpp / 8;*/
- xframe.colorspace = xviddec->csp;
+ xframe.output.csp = xviddec->csp;
+ if (xviddec->width == xviddec->stride) {
+ xframe.output.plane[0] = GST_BUFFER_DATA(outbuf);
+ xframe.output.plane[1] = xframe.output.plane[0] + (xviddec->width * xviddec->height);
+ xframe.output.plane[2] = xframe.output.plane[1] + (xviddec->width * xviddec->height / 4);
+ xframe.output.stride[0] = xviddec->width;
+ xframe.output.stride[1] = xviddec->width / 2;
+ xframe.output.stride[2] = xviddec->width / 2;
+ } else {
+ xframe.output.plane[0] = GST_BUFFER_DATA(outbuf);
+ xframe.output.stride[0] = xviddec->stride;
+ }
if ((ret = xvid_decore(xviddec->handle, XVID_DEC_DECODE,
- &xframe, NULL))) {
+ &xframe, NULL)) < 0) {
gst_element_error(GST_ELEMENT(xviddec),
"Error decoding xvid frame: %s (%d)\n",
gst_xvid_error(ret), ret);
gst_buffer_unref(buf);
+ gst_buffer_unref(outbuf);
return;
}
@@ -258,112 +271,97 @@ gst_xviddec_chain (GstPad *pad,
gst_buffer_unref(buf);
}
+/*
+ * This function allows multiple structures because it
+ * can be called from sink_link().
+ */
static GstPadLinkReturn
-gst_xviddec_negotiate (GstXvidDec *xviddec)
+gst_xviddec_src_link (GstPad *pad,
+ const GstCaps *vscaps)
{
- GstPadLinkReturn ret;
- GstCaps *caps;
- struct {
- guint32 fourcc;
- gint depth, bpp;
- gint csp;
- } fmt_list[] = {
- { GST_MAKE_FOURCC('Y','U','Y','V'), 16, 16, XVID_CSP_YUY2 },
- { GST_MAKE_FOURCC('U','Y','V','Y'), 16, 16, XVID_CSP_UYVY },
- { GST_MAKE_FOURCC('Y','V','Y','U'), 16, 16, XVID_CSP_YVYU },
- { GST_MAKE_FOURCC('Y','V','1','2'), 12, 12, XVID_CSP_YV12 },
- { GST_MAKE_FOURCC('I','4','2','0'), 12, 12, XVID_CSP_I420 },
- { GST_MAKE_FOURCC('R','G','B',' '), 32, 32, XVID_CSP_RGB32 },
- { GST_MAKE_FOURCC('R','G','B',' '), 24, 24, XVID_CSP_RGB24 },
- { GST_MAKE_FOURCC('R','G','B',' '), 16, 16, XVID_CSP_RGB555 },
- { GST_MAKE_FOURCC('R','G','B',' '), 15, 16, XVID_CSP_RGB565 },
- { 0, 0, 0 }
- };
- gint i;
-
- for (i = 0; fmt_list[i].fourcc != 0; i++) {
- xviddec->csp = fmt_list[i].csp;
-
- /* try making a caps to set on the other side */
- if (fmt_list[i].fourcc == GST_MAKE_FOURCC('R','G','B',' ')) {
- guint32 r_mask = 0, b_mask = 0, g_mask = 0;
- gint endianness = 0;
- switch (fmt_list[i].depth) {
- case 15:
- endianness = G_BYTE_ORDER;
- r_mask = 0xf800; g_mask = 0x07c0; b_mask = 0x003e;
- break;
- case 16:
- endianness = G_BYTE_ORDER;
- r_mask = R_MASK_16_INT; g_mask = G_MASK_16_INT; b_mask = B_MASK_16_INT;
- break;
- case 24:
- endianness = G_BIG_ENDIAN;
- r_mask = R_MASK_24_INT; g_mask = G_MASK_24_INT; b_mask = B_MASK_24_INT;
- break;
- case 32:
- endianness = G_BIG_ENDIAN;
- r_mask = R_MASK_32_INT; g_mask = G_MASK_32_INT; b_mask = B_MASK_32_INT;
- break;
- }
- caps = gst_caps_new_simple (
- "video/x-raw-rgb",
- "width", G_TYPE_INT, xviddec->width,
- "height", G_TYPE_INT, xviddec->height,
- "depth", G_TYPE_INT, fmt_list[i].depth,
- "bpp", G_TYPE_INT, fmt_list[i].bpp,
- "endianness", G_TYPE_INT, endianness,
- "red_mask", G_TYPE_INT, r_mask,
- "green_mask", G_TYPE_INT, g_mask,
- "blue_mask", G_TYPE_INT, b_mask,
- "framerate", G_TYPE_DOUBLE, xviddec->fps,
- NULL);
- } else {
- caps = gst_caps_new_simple (
- "video/x-raw-yuv",
- "width", G_TYPE_INT, xviddec->width,
- "height", G_TYPE_INT, xviddec->height,
- "format", GST_TYPE_FOURCC, fmt_list[i].fourcc,
- "framerate", G_TYPE_DOUBLE, xviddec->fps,
- NULL);
- }
+ GstXvidDec *xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
+ GstStructure *structure = gst_caps_get_structure (vscaps, 0);
- if ((ret = gst_pad_try_set_caps(xviddec->srcpad, caps)) > 0) {
- xviddec->csp = fmt_list[i].csp;
- xviddec->bpp = fmt_list[i].bpp;
- if (gst_xviddec_setup(xviddec))
- return GST_PAD_LINK_OK;
- } else if (ret == GST_PAD_LINK_DELAYED) {
- return ret; /* don't try further (yet) */
- }
+ if (!GST_PAD_CAPS (xviddec->sinkpad))
+ return GST_PAD_LINK_DELAYED;
+
+ /* if there's something old around, remove it */
+ if (xviddec->handle) {
+ gst_xviddec_unset(xviddec);
}
- /* if we got here - it's not good */
- return GST_PAD_LINK_REFUSED;
-}
+ xviddec->csp = gst_xvid_structure_to_csp (structure, xviddec->width,
+ &xviddec->stride,
+ &xviddec->bpp);
+
+ if (xviddec->csp < 0)
+ return GST_PAD_LINK_REFUSED;
+ if (!gst_xviddec_setup(xviddec))
+ return GST_PAD_LINK_REFUSED;;
+
+ return GST_PAD_LINK_OK;
+}
static GstPadLinkReturn
-gst_xviddec_link (GstPad *pad,
- const GstCaps *vscaps)
+gst_xviddec_sink_link (GstPad *pad,
+ const GstCaps *vscaps)
{
- GstXvidDec *xviddec;
+ GstXvidDec *xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
GstStructure *structure;
- xviddec = GST_XVIDDEC(gst_pad_get_parent (pad));
-
/* if there's something old around, remove it */
if (xviddec->handle) {
gst_xviddec_unset(xviddec);
}
/* if we get here, we know the input is xvid. we
- * only need to bother with the output colorspace */
+ * only need to bother with the output colorspace,
+ * which the src_link function takes care of. */
structure = gst_caps_get_structure (vscaps, 0);
gst_structure_get_int(structure, "width", &xviddec->width);
gst_structure_get_int(structure, "height", &xviddec->height);
gst_structure_get_double(structure, "framerate", &xviddec->fps);
- return gst_xviddec_negotiate(xviddec);
+ /* re-nego? or just await src nego? */
+ if (GST_PAD_CAPS(xviddec->srcpad)) {
+ GstPadLinkReturn ret;
+ GstCaps *vscaps = gst_pad_get_caps (GST_PAD_PEER (xviddec->srcpad)), *new;
+ gint i, csp;
+
+ for (i = 0; i < gst_caps_get_size (vscaps); i++) {
+ csp = gst_xvid_structure_to_csp (gst_caps_get_structure (vscaps, i),
+ 0, NULL, NULL);
+ new = gst_xvid_csp_to_caps (csp, xviddec->width, xviddec->height, xviddec->fps);
+ ret = gst_pad_try_set_caps(xviddec->srcpad, new);
+ if (ret != GST_PAD_LINK_REFUSED)
+ return ret;
+ }
+
+ return GST_PAD_LINK_REFUSED;
+ }
+
+ return GST_PAD_LINK_OK;
+}
+
+static GstElementStateReturn
+gst_xviddec_change_state (GstElement *element)
+{
+ GstXvidDec *xviddec = GST_XVIDDEC (element);
+
+ switch (GST_STATE_PENDING (element)) {
+ case GST_STATE_PAUSED_TO_READY:
+ if (xviddec->handle) {
+ gst_xviddec_unset (xviddec);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (parent_class->change_state)
+ return parent_class->change_state (element);
+
+ return GST_STATE_SUCCESS;
}