diff -u --recursive a/ext/xvid/gstxvid.c b/ext/xvid/gstxvid.c --- a/ext/xvid/gstxvid.c 2013-08-25 01:53:20.000000000 -0700 +++ b/ext/xvid/gstxvid.c 2013-08-25 05:14:18.000000000 -0700 @@ -28,6 +28,13 @@ #include "gstxviddec.h" #include "gstxvidenc.h" +#define GST_VIDEO_COMP1_MASK_15_INT 0x7c00 +#define GST_VIDEO_COMP2_MASK_15_INT 0x03e0 +#define GST_VIDEO_COMP3_MASK_15_INT 0x001f +#define GST_VIDEO_COMP1_MASK_16_INT 0xf800 +#define GST_VIDEO_COMP2_MASK_16_INT 0x07e0 +#define GST_VIDEO_COMP3_MASK_16_INT 0x001f + gboolean gst_xvid_init (void) { @@ -96,7 +103,7 @@ if (!strcmp (mime, "video/x-raw-yuv")) { guint32 fourcc; - gst_structure_get_fourcc (structure, "format", &fourcc); + gst_structure_get_uint (structure, "format", &fourcc); switch (fourcc) { case GST_MAKE_FOURCC ('I', '4', '2', '0'): xvid_cs = XVID_CSP_I420; @@ -277,7 +284,7 @@ structure = gst_structure_new ("video/x-raw-yuv", "width", G_TYPE_INT, w, - "height", G_TYPE_INT, h, "format", GST_TYPE_FOURCC, fourcc, NULL); + "height", G_TYPE_INT, h, "format", G_TYPE_UINT, fourcc, NULL); break; } } diff -u --recursive a/ext/xvid/gstxviddec.c b/ext/xvid/gstxviddec.c --- a/ext/xvid/gstxviddec.c 2013-08-25 01:53:20.000000000 -0700 +++ b/ext/xvid/gstxviddec.c 2013-08-25 04:02:18.000000000 -0700 @@ -27,6 +27,8 @@ #include #include +#include +#include #include "gstxviddec.h" static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -45,13 +47,13 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, YV12, YVYU, UYVY }") + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE("{ I420, YUY2, YV12, YVYU, UYVY }") "; " 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_CAPS_RGB_15 "; " GST_VIDEO_CAPS_RGB_16) + 0xff0000) "; " GST_VIDEO_CAPS_MAKE("RGB15") "; " GST_VIDEO_CAPS_MAKE("RGB16")) ); GST_DEBUG_CATEGORY_STATIC (xviddec_debug); @@ -130,11 +132,9 @@ /* create the sink pad */ dec->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); gst_pad_set_chain_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_chain)); - gst_pad_set_setcaps_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_setcaps)); + (GstPadChainFunction) gst_xviddec_chain); gst_pad_set_event_function (dec->sinkpad, - GST_DEBUG_FUNCPTR (gst_xviddec_handle_sink_event)); + (GstPadEventFunction) gst_xviddec_handle_sink_event); gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); /* create the src pad */ @@ -179,19 +179,23 @@ static gboolean gst_xviddec_handle_sink_event (GstPad * pad, GstEvent * event) { + gboolean ret; GstXvidDec *dec = GST_XVIDDEC (GST_PAD_PARENT (pad)); + GstCaps* caps; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: gst_xviddec_flush_buffers (dec, TRUE); + ret = gst_pad_push_event (dec->srcpad, event); break; case GST_EVENT_FLUSH_STOP: gst_xviddec_flush_buffers (dec, FALSE); + ret = gst_pad_push_event (dec->srcpad, event); break; - case GST_EVENT_NEWSEGMENT: + case GST_EVENT_SEGMENT: /* don't really mind about the actual segment info, * but we do need to recover from this possible jump */ - /* FIXME, NEWSEGMENT is not a discontinuity. A decoder + /* FIXME, SEGMENT is not a discontinuity. A decoder * should clip the output to the segment boundaries. * Also the rate field of the segment can be used to * optimize the decoding, like skipping B frames when @@ -200,12 +204,16 @@ * discontinuities. */ dec->waiting_for_key = TRUE; + ret = gst_pad_push_event (dec->srcpad, event); break; + case GST_EVENT_CAPS: + gst_event_parse_caps (event, &caps); + ret = gst_xviddec_setcaps (dec->srcpad, caps); default: + ret = gst_pad_push_event (dec->srcpad, event); break; } - - return gst_pad_push_event (dec->srcpad, event); + return ret; } @@ -318,6 +326,13 @@ guint8 *data, *dupe = NULL; guint size; GstFlowReturn fret; + GstMapInfo buffer_info; + GstMapInfo output_buffer_info; + GstCaps *caps; + GstQuery *query; + GstBufferPool *pool; + GstStructure *config; + guint pool_size, min, max; dec = GST_XVIDDEC (GST_OBJECT_PARENT (pad)); @@ -326,17 +341,19 @@ fret = GST_FLOW_OK; + gst_buffer_map (buf, &buffer_info, GST_MAP_READWRITE); + GST_LOG_OBJECT (dec, "Received buffer of time %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT ", size %d", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_SIZE (buf)); + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), buffer_info.size); if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT)) { /* FIXME: should we do anything here, like flush the decoder? */ } - data = GST_BUFFER_DATA (buf); - size = GST_BUFFER_SIZE (buf); + data = buffer_info.data; + size = buffer_info.size; /* xvidcore overreads the input buffer, we need to alloc some extra padding * to make things work reliably */ @@ -358,13 +375,36 @@ gst_xvid_init_struct (xstats); if (outbuf == NULL) { - fret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE, - dec->outbuf_size, GST_PAD_CAPS (dec->srcpad), &outbuf); + caps = gst_pad_get_current_caps (dec->srcpad); + query = gst_query_new_allocation (caps, TRUE); + if (!gst_pad_peer_query (dec->srcpad, query)) { + /* ignore this error... */ + } + if (gst_query_get_n_allocation_pools (query) > 0) { + gst_query_parse_nth_allocation_pool (query, 0, &pool, &pool_size, &min, &max); + } else { + pool = NULL; + pool_size = 0; + min = max = 0; + } + + if (pool == NULL) { + pool = gst_video_buffer_pool_new (); + } + + config = gst_buffer_pool_get_config (pool); + gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META); + gst_buffer_pool_config_set_params (config, caps, pool_size, min, max); + gst_buffer_pool_set_config (pool, config); + gst_buffer_pool_set_active (pool, TRUE); + + fret = gst_buffer_pool_acquire_buffer (pool, &outbuf, NULL); if (fret != GST_FLOW_OK) goto done; + gst_buffer_map (outbuf, &output_buffer_info, GST_MAP_READWRITE); } - gst_xvid_image_fill (&xframe.output, GST_BUFFER_DATA (outbuf), + gst_xvid_image_fill (&xframe.output, output_buffer_info.data, dec->csp, dec->width, dec->height); ret = xvid_decore (dec->handle, XVID_DEC_DECODE, &xframe, &xstats); @@ -398,18 +438,17 @@ non keyframe timestamps can permute a bit between encode and display order, but should match for keyframes */ if (dec->have_ts) { - GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts; + GST_BUFFER_PTS (outbuf) = dec->next_ts; GST_BUFFER_DURATION (outbuf) = dec->next_dur; - dec->next_ts = GST_BUFFER_TIMESTAMP (buf); + dec->next_ts = GST_BUFFER_PTS (buf); dec->next_dur = GST_BUFFER_DURATION (buf); } else { - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); + GST_BUFFER_PTS (outbuf) = GST_BUFFER_PTS (buf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); } - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dec->srcpad)); GST_LOG_OBJECT (dec, "pushing buffer with pts %" GST_TIME_FORMAT " duration %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), + GST_TIME_ARGS (GST_BUFFER_PTS (outbuf)), GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf))); fret = gst_pad_push (dec->srcpad, outbuf); @@ -420,14 +459,16 @@ " already queued", GST_TIME_ARGS (dec->next_ts)); } else { dec->have_ts = TRUE; - dec->next_ts = GST_BUFFER_TIMESTAMP (buf); + dec->next_ts = GST_BUFFER_PTS (buf); dec->next_dur = GST_BUFFER_DURATION (buf); } + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); } done: g_free (dupe); + gst_buffer_unmap (buf, &buffer_info); gst_buffer_unref (buf); return fret; @@ -445,15 +486,19 @@ /* FIXME: shouldn't error out fatally/properly after N decoding errors? */ GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL), ("Error decoding xvid frame: %s (%d)", gst_xvid_error (ret), ret)); - if (outbuf) + if (outbuf) { + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); + } goto done; } dropping: { GST_WARNING_OBJECT (dec, "Dropping non-keyframe (seek/init)"); - if (outbuf) + if (outbuf) { + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); + } goto done; } } diff -u --recursive a/ext/xvid/gstxvidenc.c b/ext/xvid/gstxvidenc.c --- a/ext/xvid/gstxvidenc.c 2013-08-25 01:53:20.000000000 -0700 +++ b/ext/xvid/gstxvidenc.c 2013-08-25 05:12:09.000000000 -0700 @@ -39,13 +39,13 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{ I420, YUY2, YV12, YVYU, UYVY }") + GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE("{ I420, YUY2, YV12, YVYU, UYVY }") "; " 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_CAPS_RGB_15 "; " GST_VIDEO_CAPS_RGB_16) + 0xff0000) "; " GST_VIDEO_CAPS_MAKE("RGB15") "; " GST_VIDEO_CAPS_MAKE("RGB16")) ); static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -105,6 +105,8 @@ static GstCaps *gst_xvidenc_getcaps (GstPad * pad); static void gst_xvidenc_flush_buffers (GstXvidEnc * xvidenc, gboolean send); static gboolean gst_xvidenc_handle_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_xvidenc_src_query (GstPad *pad, GstObject *parent, GstQuery *query); + /* properties */ static void gst_xvidenc_set_property (GObject * object, @@ -521,13 +523,11 @@ gst_element_add_pad (GST_ELEMENT (xvidenc), xvidenc->sinkpad); gst_pad_set_chain_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_chain)); - gst_pad_set_setcaps_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_setcaps)); - gst_pad_set_getcaps_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_getcaps)); + (GstPadChainFunction) gst_xvidenc_chain); gst_pad_set_event_function (xvidenc->sinkpad, - GST_DEBUG_FUNCPTR (gst_xvidenc_handle_sink_event)); + (GstPadEventFunction) gst_xvidenc_handle_sink_event); + gst_pad_set_query_function (xvidenc->sinkpad, + gst_xvidenc_src_query); /* create the src pad */ xvidenc->srcpad = gst_pad_new_from_static_template (&src_template, "src"); @@ -583,19 +583,47 @@ static gboolean gst_xvidenc_handle_sink_event (GstPad * pad, GstEvent * event) { + gboolean ret; GstXvidEnc *xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad)); + GstCaps* caps; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_EOS: gst_xvidenc_flush_buffers (xvidenc, TRUE); + ret = gst_pad_push_event (xvidenc->srcpad, event); break; /* no flushing if flush received, buffers in encoder are considered (in the) past */ + case GST_EVENT_CAPS: + gst_event_parse_caps (event, &caps); + ret = gst_xvidenc_setcaps (xvidenc->srcpad, caps); + break; default: + ret = gst_pad_push_event (xvidenc->srcpad, event); break; } - return gst_pad_push_event (xvidenc->srcpad, event); + return ret; +} + +static gboolean +gst_xvidenc_src_query (GstPad *pad, + GstObject *parent, + GstQuery *query) +{ + gboolean ret; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CAPS: + gst_query_set_caps_result (query, gst_xvidenc_getcaps(pad)); + ret = TRUE; + break; + default: + /* just call the default handler */ + ret = gst_pad_query_default (pad, parent, query); + break; + } + return ret; } static gboolean @@ -893,7 +921,7 @@ "pixel-aspect-ratio", GST_TYPE_FRACTION, xvidenc->par_width, xvidenc->par_height, NULL); /* just to be sure */ - gst_pad_fixate_caps (xvidenc->srcpad, new_caps); + /*gst_pad_fixate_caps (xvidenc->srcpad, new_caps);*/ if (xvidenc->used_profile != 0) { switch (xvidenc->used_profile) { @@ -989,8 +1017,8 @@ GstCaps *caps; /* If we already have caps return them */ - if (GST_PAD_CAPS (pad)) - return gst_caps_ref (GST_PAD_CAPS (pad)); + if (gst_pad_get_current_caps (pad)) + return gst_caps_ref (gst_pad_get_current_caps (pad)); xvidenc = GST_XVIDENC (gst_pad_get_parent (pad)); if (!xvidenc) @@ -1002,7 +1030,7 @@ GstCaps *peercaps; guint i, n; - peercaps = gst_pad_get_caps (peer); + peercaps = gst_pad_query_caps (peer, NULL); /* Translate peercaps to YUV */ peercaps = gst_caps_make_writable (peercaps); @@ -1040,22 +1068,27 @@ xvid_enc_frame_t xframe) { GstBuffer *outbuf; + GstMapInfo output_buffer_info; + GstMapInfo input_buffer_info; gint ret; /* compressed frame should fit in the rough size of an uncompressed one */ outbuf = gst_buffer_new_and_alloc (gst_xvid_image_get_size (xvidenc->csp, xvidenc->width, xvidenc->height)); + gst_buffer_map (outbuf, &output_buffer_info, GST_MAP_READWRITE); - xframe.bitstream = (void *) GST_BUFFER_DATA (outbuf); - xframe.length = GST_BUFFER_SIZE (outbuf); + xframe.bitstream = (void *) output_buffer_info.data; + xframe.length = output_buffer_info.size; /* now provide input image data where-abouts, if needed */ - if (buf) - gst_xvid_image_fill (&xframe.input, GST_BUFFER_DATA (buf), xvidenc->csp, + if (buf) { + gst_buffer_map (buf, &input_buffer_info, GST_MAP_READWRITE); + gst_xvid_image_fill (&xframe.input, input_buffer_info.data, xvidenc->csp, xvidenc->width, xvidenc->height); + } GST_DEBUG_OBJECT (xvidenc, "encoding frame into buffer of size %d", - GST_BUFFER_SIZE (outbuf)); + output_buffer_info.size); ret = xvid_encore (xvidenc->handle, XVID_ENC_ENCODE, &xframe, NULL); if (ret < 0) { @@ -1063,21 +1096,25 @@ if (buf) { GST_ELEMENT_WARNING (xvidenc, LIBRARY, ENCODE, (NULL), ("Error encoding xvid frame: %s (%d)", gst_xvid_error (ret), ret)); + gst_buffer_unmap (buf, &input_buffer_info); gst_buffer_unref (buf); } + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); return NULL; } else if (ret > 0) { /* make sub-buffer */ GstBuffer *sub; GST_DEBUG_OBJECT (xvidenc, "xvid produced output of size %d", ret); - sub = gst_buffer_create_sub (outbuf, 0, ret); + sub = gst_buffer_copy_region (outbuf, GST_BUFFER_COPY_ALL, 0, ret); /* parent no longer needed, will go away with child buffer */ + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); outbuf = sub; } else { /* encoder did not yet produce something */ GST_DEBUG_OBJECT (xvidenc, "xvid produced no output"); + gst_buffer_unmap (outbuf, &output_buffer_info); gst_buffer_unref (outbuf); g_queue_push_tail (xvidenc->delay, buf); return NULL; @@ -1086,7 +1123,6 @@ /* finish decoration and return */ if (!(xframe.out_flags & XVID_KEYFRAME)) GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (xvidenc->srcpad)); /* now we need the right buf to take timestamps from; note that timestamps from a display order input buffer can end up with @@ -1099,8 +1135,9 @@ buf = g_queue_pop_head (xvidenc->delay); } if (buf) { - GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); + GST_BUFFER_DTS (outbuf) = GST_BUFFER_DTS (buf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); + gst_buffer_unmap (buf, &input_buffer_info); gst_buffer_unref (buf); } @@ -1112,6 +1149,7 @@ { GstXvidEnc *xvidenc = GST_XVIDENC (GST_PAD_PARENT (pad)); GstBuffer *outbuf; + GstMapInfo buffer_info; xvid_enc_frame_t xframe; const gint motion_presets[] = { @@ -1128,10 +1166,10 @@ gst_buffer_unref (buf); return GST_FLOW_NOT_NEGOTIATED; } - + gst_buffer_map (buf, &buffer_info, GST_MAP_READWRITE); GST_DEBUG_OBJECT (xvidenc, "Received buffer of time %" GST_TIME_FORMAT ", size %d", - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_SIZE (buf)); + GST_TIME_ARGS (GST_BUFFER_DTS (buf)), buffer_info.size); if (xvidenc->xframe_cache) memcpy (&xframe, xvidenc->xframe_cache, sizeof (xframe)); @@ -1225,6 +1263,8 @@ outbuf = gst_xvidenc_encode (xvidenc, buf, xframe); + gst_buffer_unmap (buf, &buffer_info); + if (!outbuf) /* error or no data yet */ return GST_FLOW_OK; @@ -1403,3 +1443,4 @@ done: return ret; } +