From 9536cc03c0961801c823168ee2af7831e7cd458c Mon Sep 17 00:00:00 2001 From: Edgard Lima Date: Mon, 19 Dec 2005 14:40:22 +0000 Subject: divxdec and divxenc ported to 0.10 Original commit message from CVS: divxdec and divxenc ported to 0.10 --- ext/divx/Makefile.am | 11 +- ext/divx/gstdivxdec.c | 309 ++++++++++++++++++++++++++++++++------------------ ext/divx/gstdivxdec.h | 4 +- ext/divx/gstdivxenc.c | 146 ++++++++++++++---------- ext/divx/gstdivxenc.h | 2 +- 5 files changed, 295 insertions(+), 177 deletions(-) (limited to 'ext/divx') diff --git a/ext/divx/Makefile.am b/ext/divx/Makefile.am index e5323e11..8eee5b86 100644 --- a/ext/divx/Makefile.am +++ b/ext/divx/Makefile.am @@ -1,14 +1,15 @@ -plugin_LTLIBRARIES = libgstdivxenc.la libgstdivxdec.la +plugin_LTLIBRARIES = libgstdivxdec.la +plugin_LTLIBRARIES = libgstdivxenc.la libgstdivxenc_la_SOURCES = gstdivxenc.c -libgstdivxenc_la_CFLAGS = $(GST_CFLAGS) $(DIVX_CFLAGS) -libgstdivxenc_la_LIBADD = $(DIVXENC_LIBS) +libgstdivxenc_la_CFLAGS = $(GST_CFLAGS) $(DIVX_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstdivxenc_la_LIBADD = $(DIVXENC_LIBS) $(GST_PLUGINS_BASE_LIBS) libgstdivxenc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdivxdec_la_SOURCES = gstdivxdec.c -libgstdivxdec_la_CFLAGS = $(GST_CFLAGS) $(DIVX_CFLAGS) -libgstdivxdec_la_LIBADD = $(DIVXDEC_LIBS) +libgstdivxdec_la_CFLAGS = $(GST_CFLAGS) $(DIVX_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstdivxdec_la_LIBADD = $(DIVXDEC_LIBS) $(GST_PLUGINS_BASE_LIBS) libgstdivxdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstdivxenc.h gstdivxdec.h diff --git a/ext/divx/gstdivxdec.c b/ext/divx/gstdivxdec.c index 543bff3f..29b838e2 100644 --- a/ext/divx/gstdivxdec.c +++ b/ext/divx/gstdivxdec.c @@ -39,7 +39,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_CAPS ("video/x-divx, " "divxversion = (int) [ 3, 5 ], " "width = (int) [ 16, 4096 ], " - "height = (int) [ 16, 4096 ], " "framerate = (double) [ 0, MAX ]") + "height = (int) [ 16, 4096 ], " "framerate = (fraction) [0/1, MAX]") ); static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -69,11 +69,11 @@ static void gst_divxdec_base_init (GstDivxDecClass * klass); static void gst_divxdec_class_init (GstDivxDecClass * klass); static void gst_divxdec_init (GstDivxDec * divxdec); static void gst_divxdec_dispose (GObject * object); -static void gst_divxdec_chain (GstPad * pad, GstData * data); -static GstPadLinkReturn gst_divxdec_connect (GstPad * pad, - const GstCaps * vscapslist); -static GstPadLinkReturn gst_divxdec_negotiate (GstDivxDec * divxdec); - +static GstFlowReturn gst_divxdec_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_divxdec_connect (GstPad * pad, GstCaps * vscapslist); +static gboolean gst_divxdec_negotiate (GstDivxDec * divxdec); +static GstStateChangeReturn +gst_divxdec_change_state (GstElement * element, GstStateChange transition); static GstElementClass *parent_class = NULL; /* static guint gst_divxdec_signals[LAST_SIGNAL] = { 0 }; */ @@ -150,10 +150,12 @@ gst_divxdec_base_init (GstDivxDecClass * klass) static void gst_divxdec_class_init (GstDivxDecClass * klass) { + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); GObjectClass *gobject_class = (GObjectClass *) klass; parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gstelement_class->change_state = gst_divxdec_change_state; gobject_class->dispose = gst_divxdec_dispose; } @@ -167,14 +169,14 @@ gst_divxdec_init (GstDivxDec * divxdec) "sink"); gst_element_add_pad (GST_ELEMENT (divxdec), divxdec->sinkpad); gst_pad_set_chain_function (divxdec->sinkpad, gst_divxdec_chain); - gst_pad_set_link_function (divxdec->sinkpad, gst_divxdec_connect); + gst_pad_set_setcaps_function (divxdec->sinkpad, gst_divxdec_connect); /* create the src pad */ divxdec->srcpad = gst_pad_new_from_template (gst_static_pad_template_get (&src_template), "src"); gst_element_add_pad (GST_ELEMENT (divxdec), divxdec->srcpad); - gst_pad_use_explicit_caps (divxdec->srcpad); + gst_pad_use_fixed_caps (divxdec->srcpad); /* bitrate, etc. */ divxdec->width = divxdec->height = divxdec->csp = divxdec->bitcnt = -1; @@ -244,11 +246,9 @@ gst_divxdec_setup (GstDivxDec * divxdec) gst_divxdec_unset (divxdec); return FALSE; } - return TRUE; } - static void gst_divxdec_dispose (GObject * object) { @@ -258,28 +258,19 @@ gst_divxdec_dispose (GObject * object) G_OBJECT_CLASS (parent_class)->dispose (object); } - -static void -gst_divxdec_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_divxdec_chain (GstPad * pad, GstBuffer * buf) { - GstBuffer *buf = GST_BUFFER (_data); GstDivxDec *divxdec; GstBuffer *outbuf; DEC_FRAME xframe; - int ret; - - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - divxdec = GST_DIVXDEC (GST_OBJECT_PARENT (pad)); + int res; + GstFlowReturn ret; + divxdec = GST_DIVXDEC (gst_pad_get_parent (pad)); if (!divxdec->handle) { if (gst_divxdec_negotiate (divxdec) <= 0) { - GST_ELEMENT_ERROR (divxdec, CORE, TOO_LAZY, (NULL), - ("No format set - aborting")); - gst_buffer_unref (buf); - return; + goto not_negotiated; } } @@ -296,15 +287,37 @@ gst_divxdec_chain (GstPad * pad, GstData * _data) xframe.stride = 0; xframe.render_flag = 1; - if ((ret = decore (divxdec->handle, DEC_OPT_FRAME, &xframe, NULL))) { + if ((res = decore (divxdec->handle, DEC_OPT_FRAME, &xframe, NULL))) { + goto not_decoding; + } + + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (divxdec->srcpad)); + ret = gst_pad_push (divxdec->srcpad, outbuf); + goto cleanup; + +not_negotiated: + { + GST_ELEMENT_ERROR (divxdec, CORE, TOO_LAZY, (NULL), + ("No format set - aborting")); + ret = GST_FLOW_NOT_NEGOTIATED; + goto cleanup; + } + +not_decoding: + { GST_ELEMENT_ERROR (divxdec, STREAM, DECODE, (NULL), - ("Error decoding divx frame: %s (%d)", gst_divxdec_error (ret), ret)); - gst_buffer_unref (buf); - return; + ("Error decoding divx frame: %s (%d)", gst_divxdec_error (res), res)); + gst_buffer_unref (outbuf); + ret = GST_FLOW_ERROR; + goto cleanup; } - gst_pad_push (divxdec->srcpad, GST_DATA (outbuf)); +cleanup: + gst_buffer_unref (buf); + gst_object_unref (divxdec); + return ret; + } @@ -312,85 +325,89 @@ gst_divxdec_chain (GstPad * pad, GstData * _data) * stays clear */ /* -{ + { GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 32, 32, -#if (G_BYTE_ORDER == G_BIG_ENDIAN) -GST_MAKE_FOURCC ('A', 'B', 'G', 'R'), 32} + #if (G_BYTE_ORDER == G_BIG_ENDIAN) + GST_MAKE_FOURCC ('A', 'B', 'G', 'R'), 32} -, -#else -0, 32} + , + #else + 0, 32} -, -#endif -{ + , + #endif + { GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 24, 24, -#if (G_BYTE_ORDER == G_BIG_ENDIAN) -GST_MAKE_FOURCC ('A', 'B', 'G', 'R'), 24} + #if (G_BYTE_ORDER == G_BIG_ENDIAN) + GST_MAKE_FOURCC ('A', 'B', 'G', 'R'), 24} -, -#else -0, 24} + , + #else + 0, 24} -, -#endif -{ -GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 16, 16, 3, 16} + , + #endif + { + GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 16, 16, 3, 16} -, { -GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 15, 16, 0, 16} + , { + GST_MAKE_FOURCC ('R', 'G', 'B', ' '), 15, 16, 0, 16} -, -#endif - if (fmt_list[i].fourcc == GST_MAKE_FOURCC ('R', 'G', 'B', ' ')) { + , + #endif + 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 = 0xf800; - g_mask = 0x07e0; - b_mask = 0x001f; - break; - case 24: - endianness = G_BIG_ENDIAN; - r_mask = GST_VIDEO_BYTE1_MASK_24_INT; - g_mask = GST_VIDEO_BYTE2_MASK_24_INT; - b_mask = GST_VIDEO_BYTE3_MASK_24_INT break; - case 32: - endianness = G_BIG_ENDIAN; - r_mask = GST_VIDEO_BYTE1_MASK_32_INT; - g_mask = GST_VIDEO_BYTE2_MASK_32_INT; - b_mask = GST_VIDEO_BYTE3_MASK_32_INT break; + case 15: + endianness = G_BYTE_ORDER; + r_mask = 0xf800; + g_mask = 0x07c0; + b_mask = 0x003e; + break; + case 16: + endianness = G_BYTE_ORDER; + r_mask = 0xf800; + g_mask = 0x07e0; + b_mask = 0x001f; + break; + case 24: + endianness = G_BIG_ENDIAN; + r_mask = GST_VIDEO_BYTE1_MASK_24_INT; + g_mask = GST_VIDEO_BYTE2_MASK_24_INT; + b_mask = GST_VIDEO_BYTE3_MASK_24_INT break; + case 32: + endianness = G_BIG_ENDIAN; + r_mask = GST_VIDEO_BYTE1_MASK_32_INT; + g_mask = GST_VIDEO_BYTE2_MASK_32_INT; + b_mask = GST_VIDEO_BYTE3_MASK_32_INT break; } caps = GST_CAPS_NEW ("divxdec_src_pad_rgb", - "video/x-raw-rgb", - "width", GST_PROPS_INT (divxdec->width), - "height", GST_PROPS_INT (divxdec->height), - "framerate", GST_PROPS_FLOAT (divxdec->fps), - "depth", GST_PROPS_INT (fmt_list[i].depth), - "bpp", GST_PROPS_INT (fmt_list[i].bpp), - "endianness", GST_PROPS_INT (endianness), - "red_mask", GST_PROPS_INT (r_mask), - "green_mask", GST_PROPS_INT (g_mask), - "blue_mask", GST_PROPS_INT (b_mask)); -} else { -#endif - -#endif + "video/x-raw-rgb", + "width", GST_PROPS_INT (divxdec->width), + "height", GST_PROPS_INT (divxdec->height), + "framerate", GST_PROPS_FLOAT (divxdec->fps), + "depth", GST_PROPS_INT (fmt_list[i].depth), + "bpp", GST_PROPS_INT (fmt_list[i].bpp), + "endianness", GST_PROPS_INT (endianness), + "red_mask", GST_PROPS_INT (r_mask), + "green_mask", GST_PROPS_INT (g_mask), + "blue_mask", GST_PROPS_INT (b_mask)); + } else { + #endif + + #endif */ -static GstPadLinkReturn +static gboolean gst_divxdec_negotiate (GstDivxDec * divxdec) { - GstCaps *caps; + GstCaps *caps = NULL; + gint i; + gint par_num, par_den; + gboolean ret = FALSE; + struct { guint32 fourcc; @@ -398,6 +415,7 @@ gst_divxdec_negotiate (GstDivxDec * divxdec) guint32 csp; gint bitcnt; } + fmt_list[] = { { GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), 16, 16, @@ -414,7 +432,18 @@ gst_divxdec_negotiate (GstDivxDec * divxdec) , { 0, 0, 0, 0, 0} }; - gint i; + + GST_DEBUG_OBJECT (divxdec, "fps %d/%d, PAR %d/%d", + divxdec->fps_n, divxdec->fps_d, divxdec->par_n, divxdec->par_d); + + /* calculate par + * the info.aspect_* values reflect PAR; + * 0:0 is allowed and can be interpreted as 1:1, so correct for it */ + par_num = divxdec->par_n; + par_den = divxdec->par_d; + if (par_num == 0 && par_den == 0) { + par_num = par_den = 1; + } for (i = 0; fmt_list[i].fourcc != 0; i++) { divxdec->csp = fmt_list[i].csp; @@ -422,27 +451,48 @@ gst_divxdec_negotiate (GstDivxDec * divxdec) caps = gst_caps_new_simple ("video/x-raw-yuv", "width", G_TYPE_INT, divxdec->width, "height", G_TYPE_INT, divxdec->height, - "framerate", G_TYPE_DOUBLE, divxdec->fps, + "framerate", GST_TYPE_FRACTION, divxdec->fps_n, divxdec->fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den, "format", GST_TYPE_FOURCC, fmt_list[i].fourcc, NULL); - if (gst_divxdec_setup (divxdec) && - gst_pad_set_explicit_caps (divxdec->srcpad, caps)) { - divxdec->csp = fmt_list[i].csp; - divxdec->bpp = fmt_list[i].bpp; - divxdec->bitcnt = fmt_list[i].bitcnt; - return GST_PAD_LINK_OK; + if (caps) { + + if (gst_divxdec_setup (divxdec) && + gst_pad_set_caps (divxdec->srcpad, caps)) { + divxdec->csp = fmt_list[i].csp; + divxdec->bpp = fmt_list[i].bpp; + divxdec->bitcnt = fmt_list[i].bitcnt; + ret = TRUE; + goto done; + } + + gst_caps_unref (caps); + caps = NULL; + } + } /* if we got here - it's not good */ - return GST_PAD_LINK_REFUSED; + +done: + + if (caps) { + gst_caps_unref (caps); + } + + return ret; } -static GstPadLinkReturn -gst_divxdec_connect (GstPad * pad, const GstCaps * caps) +static gboolean +gst_divxdec_connect (GstPad * pad, GstCaps * caps) { GstDivxDec *divxdec; + const GValue *par; + const GValue *fps; + gboolean ret = FALSE; + GstStructure *structure = gst_caps_get_structure (caps, 0); divxdec = GST_DIVXDEC (gst_pad_get_parent (pad)); @@ -452,18 +502,61 @@ gst_divxdec_connect (GstPad * pad, const GstCaps * caps) gst_divxdec_unset (divxdec); } - /* we are not going to act on variable caps */ - if (!gst_caps_is_fixed (caps)) - return GST_PAD_LINK_DELAYED; - /* if we get here, we know the input is divx. we * only need to bother with the output colorspace */ gst_structure_get_int (structure, "width", &divxdec->width); gst_structure_get_int (structure, "height", &divxdec->height); - gst_structure_get_double (structure, "framerate", &divxdec->fps); gst_structure_get_int (structure, "divxversion", &divxdec->version); - return gst_divxdec_negotiate (divxdec); + /* get pixel aspect ratio if it's set */ + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (par) { + divxdec->par_n = gst_value_get_fraction_numerator (par), + divxdec->par_d = gst_value_get_fraction_denominator (par); + } + + fps = gst_structure_get_value (structure, "framerate"); + if (fps != NULL) { + divxdec->fps_n = gst_value_get_fraction_numerator (fps); + divxdec->fps_d = gst_value_get_fraction_denominator (fps); + } else { + divxdec->fps_n = -1; + } + + ret = gst_divxdec_negotiate (divxdec); + gst_object_unref (divxdec); + + return ret; +} + +static GstStateChangeReturn +gst_divxdec_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; } diff --git a/ext/divx/gstdivxdec.h b/ext/divx/gstdivxdec.h index 0468ff0a..90c47037 100644 --- a/ext/divx/gstdivxdec.h +++ b/ext/divx/gstdivxdec.h @@ -56,7 +56,9 @@ struct _GstDivxDec { int bitcnt, bpp; int version; int width, height; - gdouble fps; + + gint fps_n, fps_d; + gint par_n, par_d; }; struct _GstDivxDecClass { diff --git a/ext/divx/gstdivxenc.c b/ext/divx/gstdivxenc.c index 591bb90e..5269e01e 100644 --- a/ext/divx/gstdivxenc.c +++ b/ext/divx/gstdivxenc.c @@ -48,7 +48,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS ("video/x-divx, " "divxversion = (int) 5, " "width = (int) [ 16, 4096 ], " - "height = (int) [ 16, 4096 ], " "framerate = (double) [ 0, MAX ]") + "height = (int) [ 16, 4096 ], " "framerate = (fraction) [0/1, MAX]") ); @@ -73,9 +73,8 @@ static void gst_divxenc_class_init (GstDivxEncClass * klass); static void gst_divxenc_base_init (GstDivxEncClass * klass); static void gst_divxenc_init (GstDivxEnc * divxenc); static void gst_divxenc_dispose (GObject * object); -static void gst_divxenc_chain (GstPad * pad, GstData * data); -static GstPadLinkReturn gst_divxenc_connect (GstPad * pad, - const GstCaps * vscapslist); +static GstFlowReturn gst_divxenc_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_divxenc_setcaps (GstPad * pad, GstCaps * caps); /* properties */ static void gst_divxenc_set_property (GObject * object, @@ -162,13 +161,12 @@ gst_divxenc_base_init (GstDivxEncClass * klass) static void gst_divxenc_class_init (GstDivxEncClass * klass) { - GstElementClass *gstelement_class; - GObjectClass *gobject_class; + GObjectClass *gobject_class = (GObjectClass *) klass; - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; + parent_class = g_type_class_peek_parent (klass); - parent_class = g_type_class_ref (GST_TYPE_ELEMENT); + gobject_class->set_property = gst_divxenc_set_property; + gobject_class->get_property = gst_divxenc_get_property; g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE, g_param_spec_ulong ("bitrate", "Bitrate", @@ -187,9 +185,6 @@ gst_divxenc_class_init (GstDivxEncClass * klass) g_param_spec_int ("quality", "Quality", "Amount of Motion Estimation", 1, 5, 3, G_PARAM_READWRITE)); - gobject_class->set_property = gst_divxenc_set_property; - gobject_class->get_property = gst_divxenc_get_property; - gobject_class->dispose = gst_divxenc_dispose; gst_divxenc_signals[FRAME_ENCODED] = @@ -210,13 +205,13 @@ gst_divxenc_init (GstDivxEnc * divxenc) gst_element_add_pad (GST_ELEMENT (divxenc), divxenc->sinkpad); gst_pad_set_chain_function (divxenc->sinkpad, gst_divxenc_chain); - gst_pad_set_link_function (divxenc->sinkpad, gst_divxenc_connect); + gst_pad_set_setcaps_function (divxenc->sinkpad, gst_divxenc_setcaps); /* create the src pad */ divxenc->srcpad = gst_pad_new_from_template (gst_static_pad_template_get (&src_template), "src"); - gst_pad_use_explicit_caps (divxenc->srcpad); + gst_pad_use_fixed_caps (divxenc->srcpad); gst_element_add_pad (GST_ELEMENT (divxenc), divxenc->srcpad); /* bitrate, etc. */ @@ -254,7 +249,7 @@ gst_divxenc_setup (GstDivxEnc * divxenc) output.use_bidirect = 1; output.input_clock = 0; output.input_frame_period = 1000000; - output.internal_timescale = divxenc->fps * 1000000; + output.internal_timescale = (divxenc->fps_n / divxenc->fps_d) * 1000000; /* FIX? */ output.max_key_interval = (divxenc->max_key_interval == -1) ? 150 : divxenc->max_key_interval; output.key_frame_threshold = 50; @@ -314,21 +309,17 @@ gst_divxenc_dispose (GObject * object) } -static void -gst_divxenc_chain (GstPad * pad, GstData * _data) +static GstFlowReturn +gst_divxenc_chain (GstPad * pad, GstBuffer * buf) { - GstBuffer *buf = GST_BUFFER (_data); GstDivxEnc *divxenc; GstBuffer *outbuf; ENC_FRAME xframe; ENC_RESULT xres; - int ret; + int res; + GstFlowReturn ret = GST_FLOW_OK; - g_return_if_fail (pad != NULL); - g_return_if_fail (GST_IS_PAD (pad)); - g_return_if_fail (buf != NULL); - - divxenc = GST_DIVXENC (GST_OBJECT_PARENT (pad)); + divxenc = GST_DIVXENC (gst_pad_get_parent (pad)); outbuf = gst_buffer_new_and_alloc (divxenc->buffer_size); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); @@ -336,28 +327,38 @@ gst_divxenc_chain (GstPad * pad, GstData * _data) /* encode and so ... */ xframe.image = GST_BUFFER_DATA (buf); xframe.bitstream = (void *) GST_BUFFER_DATA (outbuf); - xframe.length = GST_BUFFER_MAXSIZE (outbuf); + xframe.length = GST_BUFFER_SIZE (outbuf); /* GST_BUFFER_MAXSIZE */ xframe.produce_empty_frame = 0; - if ((ret = encore (divxenc->handle, ENC_OPT_ENCODE, &xframe, &xres))) { - GST_ELEMENT_ERROR (divxenc, LIBRARY, ENCODE, (NULL), - ("Error encoding divx frame: %s (%d)", gst_divxenc_error (ret), ret)); - gst_buffer_unref (buf); - return; + if ((res = encore (divxenc->handle, ENC_OPT_ENCODE, &xframe, &xres))) { + goto not_encoding; } GST_BUFFER_SIZE (outbuf) = xframe.length; - if (xres.cType == 'I') - GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_KEY_UNIT); /* go out, multiply! */ - gst_pad_push (divxenc->srcpad, GST_DATA (outbuf)); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (divxenc->srcpad)); + gst_pad_push (divxenc->srcpad, outbuf); /* proclaim destiny */ g_signal_emit (G_OBJECT (divxenc), gst_divxenc_signals[FRAME_ENCODED], 0); /* until the final judgement */ + goto done; + +not_encoding: + + GST_ELEMENT_ERROR (divxenc, LIBRARY, ENCODE, (NULL), + ("Error encoding divx frame: %s (%d)", gst_divxenc_error (res), res)); + ret = GST_FLOW_ERROR; + gst_buffer_unref (outbuf); + goto done; + +done: gst_buffer_unref (buf); + gst_object_unref (divxenc); + return ret; + } /* FIXME: moving broken bits here for others to fix */ @@ -366,26 +367,27 @@ gst_divxenc_chain (GstPad * pad, GstData * _data) case GST_MAKE_FOURCC ('R', 'G', 'B', ' '): gst_caps_get_int (caps, "depth", &d); switch (d) { - case 24: - divx_cs = 0; - bitcnt = 24; - break; - case 32: - divx_cs = 0; - bitcnt = 32; - break; + case 24: + divx_cs = 0; + bitcnt = 24; + break; + case 32: + divx_cs = 0; + bitcnt = 32; + break; */ -static GstPadLinkReturn -gst_divxenc_connect (GstPad * pad, const GstCaps * caps) +static gboolean +gst_divxenc_setcaps (GstPad * pad, GstCaps * caps) { GstDivxEnc *divxenc; GstStructure *structure = gst_caps_get_structure (caps, 0); gint w, h; - gdouble fps; + const GValue *fps; guint32 fourcc; guint32 divx_cs; gint bitcnt = 0; + gboolean ret = FALSE; divxenc = GST_DIVXENC (gst_pad_get_parent (pad)); @@ -394,9 +396,16 @@ gst_divxenc_connect (GstPad * pad, const GstCaps * caps) gst_structure_get_int (structure, "width", &w); gst_structure_get_int (structure, "height", &h); - gst_structure_get_double (structure, "framerate", &fps); gst_structure_get_fourcc (structure, "format", &fourcc); + fps = gst_structure_get_value (structure, "framerate"); + if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) { + divxenc->fps_n = gst_value_get_fraction_numerator (fps); + divxenc->fps_d = gst_value_get_fraction_denominator (fps); + } else { + divxenc->fps_n = -1; + } + switch (fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): divx_cs = GST_MAKE_FOURCC ('I', '4', '2', '0'); @@ -414,35 +423,47 @@ gst_divxenc_connect (GstPad * pad, const GstCaps * caps) divx_cs = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); break; default: - return GST_PAD_LINK_REFUSED; + ret = FALSE; + goto done; } divxenc->csp = divx_cs; divxenc->bitcnt = bitcnt; divxenc->width = w; divxenc->height = h; - divxenc->fps = fps; /* try it */ if (gst_divxenc_setup (divxenc)) { - GstPadLinkReturn ret; - GstCaps *new_caps; + GstCaps *new_caps = NULL; new_caps = gst_caps_new_simple ("video/x-divx", "divxversion", G_TYPE_INT, 5, "width", G_TYPE_INT, w, - "height", G_TYPE_INT, h, "framerate", G_TYPE_DOUBLE, fps, NULL); + "height", G_TYPE_INT, h, + "framerate", GST_TYPE_FRACTION, divxenc->fps_n, divxenc->fps_d, NULL); + + if (new_caps) { + + if (!gst_pad_set_caps (divxenc->srcpad, new_caps)) { + gst_divxenc_unset (divxenc); + ret = FALSE; + goto done; + } + gst_caps_unref (new_caps); + ret = TRUE; + goto done; - ret = gst_pad_set_explicit_caps (divxenc->srcpad, new_caps); - if (ret <= 0) { - gst_divxenc_unset (divxenc); } - return ret; } /* if we got here - it's not good */ - return GST_PAD_LINK_REFUSED; + + ret = FALSE; + +done: + gst_object_unref (divxenc); + return ret; } @@ -450,10 +471,9 @@ static void gst_divxenc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstDivxEnc *divxenc; + GstDivxEnc *divxenc = GST_DIVXENC (object); - g_return_if_fail (GST_IS_DIVXENC (object)); - divxenc = GST_DIVXENC (object); + GST_OBJECT_LOCK (divxenc); switch (prop_id) { case ARG_BITRATE: @@ -469,6 +489,8 @@ gst_divxenc_set_property (GObject * object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (divxenc); } @@ -476,10 +498,9 @@ static void gst_divxenc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstDivxEnc *divxenc; + GstDivxEnc *divxenc = GST_DIVXENC (object); - g_return_if_fail (GST_IS_DIVXENC (object)); - divxenc = GST_DIVXENC (object); + GST_OBJECT_LOCK (divxenc); switch (prop_id) { case ARG_BITRATE: @@ -498,8 +519,9 @@ gst_divxenc_get_property (GObject * object, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } -} + GST_OBJECT_UNLOCK (divxenc); +} static gboolean plugin_init (GstPlugin * plugin) diff --git a/ext/divx/gstdivxenc.h b/ext/divx/gstdivxenc.h index 206659d3..0d5cad05 100644 --- a/ext/divx/gstdivxenc.h +++ b/ext/divx/gstdivxenc.h @@ -64,7 +64,7 @@ struct _GstDivxEnc { guint32 csp; gint bitcnt; gint width, height; - gfloat fps; + gint fps_n, fps_d; }; struct _GstDivxEncClass { -- cgit v1.2.1