+2005-05-17 Wim Taymans <wim@fluendo.com>
+
+ * ext/ogg/gstoggdemux.c: (gst_ogg_pad_internal_chain),
+ (gst_ogg_demux_submit_buffer), (gst_ogg_demux_get_data),
+ (gst_ogg_demux_chain_unlocked):
+ * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_chain),
+ (gst_audio_convert_caps_remove_format_info),
+ (gst_audio_convert_getcaps), (gst_audio_convert_setcaps),
+ (gst_audio_convert_fixate), (gst_audio_convert_change_state):
+ * gst/ffmpegcolorspace/gstffmpegcolorspace.c:
+ (gst_ffmpegcsp_getcaps), (gst_ffmpegcsp_configure_context),
+ (gst_ffmpegcsp_setcaps), (gst_ffmpegcsp_init),
+ (gst_ffmpegcsp_bufferalloc), (gst_ffmpegcsp_chain),
+ (gst_ffmpegcsp_change_state), (gst_ffmpegcsp_set_property),
+ (gst_ffmpegcsp_get_property):
+ * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy),
+ (gst_xvimage_buffer_finalize), (gst_xvimage_buffer_free),
+ (gst_xvimage_buffer_class_init), (gst_xvimage_buffer_get_type),
+ (gst_xvimagesink_check_xshm_calls), (gst_xvimagesink_xvimage_new),
+ (gst_xvimagesink_xvimage_put), (gst_xvimagesink_imagepool_clear),
+ (gst_xvimagesink_setcaps), (gst_xvimagesink_change_state),
+ (gst_xvimagesink_show_frame), (gst_xvimagesink_buffer_free),
+ (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id):
+ Leak fixes in oggdemux.
+ Some cleanups in audioconvert.
+ Make passthrough work along with buffer_alloc etc.
+ Make buffer_alloc and buffer recycling actually work in
+ xvimagesink.
+
2005-05-17 Thomas Vander Stichele <thomas at apestaart dot org>
* gst/subparse/gstsubparse.c: (parse_subrip), (parse_mpsub):
if (oggpad->start_time == -1)
oggpad->start_time = timestamp;
+ gst_buffer_unref (buffer);
+
return GST_FLOW_OK;
}
oggbuffer = ogg_sync_buffer (&ogg->sync, size);
memcpy (oggbuffer, data, size);
ogg_sync_wrote (&ogg->sync, size);
+ gst_buffer_unref (buffer);
return size;
}
return -1;
size = gst_ogg_demux_submit_buffer (ogg, buffer);
- gst_buffer_unref (buffer);
return size;
}
}
}
}
- gst_buffer_unref (buffer);
return result;
}
static GstElementStateReturn
gst_audio_convert_change_state (GstElement * element)
{
+ GstElementStateReturn ret;
GstAudioConvert *this = GST_AUDIO_CONVERT (element);
+ gint transition;
- switch (GST_STATE_TRANSITION (element)) {
+ transition = GST_STATE_TRANSITION (element);
+
+ switch (transition) {
+ default:
+ break;
+ }
+
+ ret = parent_class->change_state (element);
+
+ switch (transition) {
case GST_STATE_PAUSED_TO_READY:
GST_STREAM_LOCK (this->sink);
this->convert_internal = NULL;
gst_audio_convert_unset_matrix (this);
+ gst_caps_replace (&GST_RPAD_CAPS (this->sink), NULL);
+ gst_caps_replace (&GST_RPAD_CAPS (this->src), NULL);
GST_STREAM_UNLOCK (this->sink);
break;
default:
break;
}
-
- if (parent_class->change_state) {
- return parent_class->change_state (element);
- } else {
- return GST_STATE_SUCCESS;
- }
+ return ret;
}
/* return a writable buffer of size which ideally is the same as before
static void gst_ffmpegcsp_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
+static GstBuffer *gst_ffmpegcsp_bufferalloc (GstPad * pad, guint64 offset,
+ guint size, GstCaps * caps);
static GstFlowReturn gst_ffmpegcsp_chain (GstPad * pad, GstBuffer * buffer);
static GstElementStateReturn gst_ffmpegcsp_change_state (GstElement * element);
par = gst_structure_get_value (structure, "pixel-aspect-ratio");
if (!gst_ffmpegcsp_configure_context (pad, caps, width, height))
- goto configure_error;
+ goto configure_error_source;
- *prefered = caps;
+ gst_caps_replace (prefered, caps);
otherpeer = gst_pad_get_peer (otherpad);
if (otherpeer) {
/* check passthrough */
if (gst_pad_accept_caps (otherpeer, caps)) {
- *other_prefered = gst_caps_ref (caps);
+ if (!gst_ffmpegcsp_configure_context (otherpad, caps, width, height))
+ goto configure_error_target;
+ gst_caps_replace (other_prefered, caps);
} else {
GstCaps *othercaps;
gst_value_get_fraction_numerator (par),
gst_value_get_fraction_denominator (par), NULL);
}
- *other_prefered = targetcaps;
+ if (!gst_ffmpegcsp_configure_context (otherpad, targetcaps, width,
+ height)) {
+ gst_caps_unref (targetcaps);
+ goto configure_error_target;
+ }
+ gst_caps_replace (other_prefered, targetcaps);
+ gst_caps_unref (targetcaps);
}
}
gst_object_unref (GST_OBJECT (otherpeer));
return TRUE;
-configure_error:
+configure_error_source:
+ {
+ GST_DEBUG ("could not configure context for source");
+ return FALSE;
+ }
+configure_error_target:
{
- GST_DEBUG ("could not configure context");
+ gst_object_unref (GST_OBJECT (otherpeer));
+ GST_DEBUG ("could not configure context for target");
return FALSE;
}
}
gst_pad_set_getcaps_function (space->sinkpad, gst_ffmpegcsp_getcaps);
gst_pad_set_setcaps_function (space->sinkpad, gst_ffmpegcsp_setcaps);
gst_pad_set_chain_function (space->sinkpad, gst_ffmpegcsp_chain);
+ gst_pad_set_bufferalloc_function (space->sinkpad, gst_ffmpegcsp_bufferalloc);
gst_element_add_pad (GST_ELEMENT (space), space->sinkpad);
space->srcpad = gst_pad_new_from_template (srctempl, "src");
space->palette = NULL;
}
+static GstBuffer *
+gst_ffmpegcsp_bufferalloc (GstPad * pad, guint64 offset, guint size,
+ GstCaps * caps)
+{
+ GstBuffer *buf;
+ GstFFMpegCsp *space;
+
+ space = GST_FFMPEGCSP (GST_PAD_PARENT (pad));
+
+ buf = gst_pad_alloc_buffer (space->srcpad, offset, size, caps);
+ return buf;
+}
+
static GstFlowReturn
gst_ffmpegcsp_chain (GstPad * pad, GstBuffer * buffer)
{
- GstBuffer *inbuf = GST_BUFFER (buffer);
GstFFMpegCsp *space;
+ GstFlowReturn res;
GstBuffer *outbuf = NULL;
- //GstCaps *outcaps;
-
space = GST_FFMPEGCSP (GST_PAD_PARENT (pad));
- if (!GST_PAD_IS_USABLE (space->srcpad)) {
- gst_buffer_unref (inbuf);
- return GST_FLOW_ERROR;
- }
-
- /* asume passthrough */
- guint size =
- avpicture_get_size (space->from_pixfmt, space->width, space->height);
-
- outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size,
- space->src_prefered);
- if (outbuf == NULL) {
- return GST_FLOW_ERROR;
- }
+ GST_STREAM_LOCK (pad);
- if (space->from_pixfmt == PIX_FMT_NB || space->to_pixfmt == PIX_FMT_NB) {
- GST_ELEMENT_ERROR (space, CORE, NOT_IMPLEMENTED, (NULL),
- ("attempting to convert colorspaces between unknown formats"));
- gst_buffer_unref (inbuf);
- return GST_FLOW_NOT_NEGOTIATED;
- }
+ if (space->from_pixfmt == PIX_FMT_NB || space->to_pixfmt == PIX_FMT_NB)
+ goto unkown_format;
if (space->from_pixfmt == space->to_pixfmt) {
- GST_DEBUG ("passthrough conversion %" GST_PTR_FORMAT,
- GST_PAD_CAPS (space->srcpad));
- outbuf = inbuf;
+ GST_DEBUG ("passthrough conversion");
+ /* use input as output buffer */
+ outbuf = buffer;
} else {
- /* convert */
+ /* get size of our suggested output format */
+ guint size =
+ avpicture_get_size (space->to_pixfmt, space->width, space->height);
+
+ /* get buffer in prefered format, setcaps will be called when it is different */
+ outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size,
+ space->src_prefered);
+ if (outbuf == NULL)
+ goto no_buffer;
+
+ /* fill from from with source data */
gst_ffmpegcsp_avpicture_fill (&space->from_frame,
- GST_BUFFER_DATA (inbuf),
+ GST_BUFFER_DATA (buffer),
space->from_pixfmt, space->width, space->height);
+
+ /* fill optional palette */
if (space->palette)
space->from_frame.data[1] = (uint8_t *) space->palette;
+
+ /* fill target frame */
gst_ffmpegcsp_avpicture_fill (&space->to_frame,
GST_BUFFER_DATA (outbuf),
space->to_pixfmt, space->width, space->height);
+
+ /* and convert */
img_convert (&space->to_frame, space->to_pixfmt,
&space->from_frame, space->from_pixfmt, space->width, space->height);
- GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
- GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
- gst_buffer_unref (inbuf);
+ /* copy timestamps */
+ GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buffer);
+ GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buffer);
+
+ /* we don't need source anymore */
+ gst_buffer_unref (buffer);
}
- return gst_pad_push (space->srcpad, outbuf);
+ res = gst_pad_push (space->srcpad, outbuf);
+ GST_STREAM_UNLOCK (pad);
+
+ return res;
+
+ /* ERRORS */
+no_buffer:
+ {
+ GST_STREAM_UNLOCK (pad);
+ gst_buffer_unref (buffer);
+ return GST_FLOW_ERROR;
+ }
+unkown_format:
+ {
+ GST_STREAM_UNLOCK (pad);
+ GST_ELEMENT_ERROR (space, CORE, NOT_IMPLEMENTED, (NULL),
+ ("attempting to convert colorspaces between unknown formats"));
+ gst_buffer_unref (buffer);
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
}
static GstElementStateReturn
gst_ffmpegcsp_change_state (GstElement * element)
{
GstFFMpegCsp *space;
+ GstElementStateReturn ret;
+ gint transition;
space = GST_FFMPEGCSP (element);
+ transition = GST_STATE_TRANSITION (element);
+
+ switch (transition) {
+ default:
+ break;
+ }
+
+ ret = parent_class->change_state (element);
- switch (GST_STATE_TRANSITION (element)) {
+ switch (transition) {
case GST_STATE_PAUSED_TO_READY:
+ GST_STREAM_LOCK (space->sinkpad);
if (space->palette)
av_free (space->palette);
space->palette = NULL;
+ GST_STREAM_UNLOCK (space->sinkpad);
+ break;
+ default:
break;
}
- if (parent_class->change_state)
- return parent_class->change_state (element);
-
- return GST_STATE_SUCCESS;
+ return ret;
}
static void
{
GstFFMpegCsp *space;
- /* it's not null if we got it, but it might not be ours */
- g_return_if_fail (GST_IS_FFMPEGCSP (object));
space = GST_FFMPEGCSP (object);
switch (prop_id) {
default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
{
GstFFMpegCsp *space;
- /* it's not null if we got it, but it might not be ours */
- g_return_if_fail (GST_IS_FFMPEGCSP (object));
space = GST_FFMPEGCSP (object);
switch (prop_id) {
/* This function destroys a GstXvImage handling XShm availability */
static void
-gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
+gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage)
{
GstXvImageSink *xvimagesink;
- g_return_if_fail (xvimage != NULL);
-
- if (xvimage->xvimagesink == NULL)
- return;
-
xvimagesink = xvimage->xvimagesink;
+ if (xvimagesink == NULL)
+ goto no_sink;
g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink));
XSync (xvimagesink->xcontext->disp, FALSE);
g_mutex_unlock (xvimagesink->x_lock);
+
+ return;
+
+no_sink:
+ {
+ GST_WARNING ("no sink found");
+ return;
+ }
+}
+
+static void
+gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage)
+{
+ GstXvImageSink *xvimagesink;
+
+ xvimagesink = xvimage->xvimagesink;
+ if (xvimagesink == NULL)
+ goto no_sink;
+
+ /* If our geometry changed we can't reuse that image. */
+ if ((xvimage->width != xvimagesink->video_width) ||
+ (xvimage->height != xvimagesink->video_height)) {
+ GST_DEBUG ("destroy image as its size changed %dx%d vs current %dx%d",
+ xvimage->width, xvimage->height,
+ xvimagesink->video_width, xvimagesink->video_height);
+ gst_xvimage_buffer_destroy (xvimage);
+ } else {
+ /* In that case we can reuse the image and add it to our image pool. */
+ GST_DEBUG ("recycling image in pool");
+ /* need to increment the refcount again to recycle */
+ gst_buffer_ref (GST_BUFFER (xvimage));
+ g_mutex_lock (xvimagesink->pool_lock);
+ xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
+ xvimage);
+ g_mutex_unlock (xvimagesink->pool_lock);
+ }
+ return;
+
+no_sink:
+ {
+ GST_WARNING ("no sink found");
+ return;
+ }
}
+static void
+gst_xvimage_buffer_free (GstXvImageBuffer * xvimage)
+{
+ /* make sure it is not recycled */
+ xvimage->width = -1;
+ xvimage->height = -1;
+ gst_buffer_unref (GST_BUFFER (xvimage));
+}
static void
gst_xvimage_buffer_init (GTypeInstance * instance, gpointer g_class)
beach:
XSetErrorHandler (handler);
- gst_buffer_unref (GST_BUFFER (xvimage));
+ gst_xvimage_buffer_free (xvimage);
XSync (xcontext->disp, FALSE);
return result;
#endif /* HAVE_XSHM */
beach:
if (!succeeded) {
- gst_buffer_unref (GST_BUFFER (xvimage));
+ gst_xvimage_buffer_free (xvimage);
xvimage = NULL;
}
xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool,
xvimagesink->image_pool);
- gst_buffer_unref (GST_BUFFER (xvimage));
+ gst_xvimage_buffer_free (xvimage);
}
g_mutex_unlock (xvimagesink->pool_lock);
GST_FOURCC_ARGS (xvimagesink->xcontext->im_format),
GST_FOURCC_ARGS (im_format));
GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage");
- gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
+ gst_xvimage_buffer_free (xvimagesink->xvimage);
xvimagesink->xvimage = NULL;
}
break;
case GST_STATE_READY_TO_NULL:
if (xvimagesink->xvimage) {
- gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
+ gst_xvimage_buffer_free (xvimagesink->xvimage);
xvimagesink->xvimage = NULL;
}
/* If this buffer has been allocated using our buffer management we simply
put the ximage which is in the PRIVATE pointer */
if (GST_IS_XVIMAGE_BUFFER (buf)) {
+ GST_DEBUG ("fast put of bufferpool buffer");
gst_xvimagesink_xvimage_put (xvimagesink, GST_XVIMAGE_BUFFER (buf));
} else {
+ GST_DEBUG ("slow copy into bufferpool buffer");
/* Else we have to copy the data into our private image, */
/* if we have one... */
if (!xvimagesink->xvimage) {
GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage");
+
xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink,
xvimagesink->video_width, xvimagesink->video_height);
- if (!xvimagesink->xvimage) {
- /* No image available. That's very bad ! */
- gst_buffer_unref (buf);
- GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
- ("Failed creating an XvImage in xvimagesink chain function."));
- return GST_FLOW_ERROR;
- }
+
+ if (!xvimagesink->xvimage)
+ goto no_image;
}
memcpy (xvimagesink->xvimage->xvimage->data,
GST_BUFFER_DATA (buf),
MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size));
+
gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage);
}
gst_xvimagesink_handle_xevents (xvimagesink, GST_VIDEOSINK_PAD (xvimagesink));
return GST_FLOW_OK;
+
+ /* ERRORS */
+no_image:
+ {
+ /* No image available. That's very bad ! */
+ gst_buffer_unref (buf);
+ GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL),
+ ("Failed creating an XvImage in xvimagesink chain function."));
+ return GST_FLOW_ERROR;
+ }
}
/* Buffer management */
static void
gst_xvimagesink_buffer_free (GstBuffer * buffer)
{
- GstXvImageSink *xvimagesink;
- GstXvImageBuffer *xvimage;
-
- xvimage = GST_BUFFER_PRIVATE (buffer);
-
- g_assert (GST_IS_XVIMAGESINK (xvimage->xvimagesink));
- xvimagesink = xvimage->xvimagesink;
-
- /* If our geometry changed we can't reuse that image. */
- if ((xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
- (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)))
- gst_xvimagesink_xvimage_destroy (xvimagesink, xvimage);
- else {
- /* In that case we can reuse the image and add it to our image pool. */
- g_mutex_lock (xvimagesink->pool_lock);
- xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool,
- xvimage);
- g_mutex_unlock (xvimagesink->pool_lock);
- }
}
#endif
xvimagesink->image_pool);
/* We check for geometry or image format changes */
- if ((xvimage->width != GST_VIDEOSINK_WIDTH (xvimagesink)) ||
- (xvimage->height != GST_VIDEOSINK_HEIGHT (xvimagesink)) ||
+ if ((xvimage->width != xvimagesink->video_width) ||
+ (xvimage->height != xvimagesink->video_height) ||
(xvimage->im_format != xvimagesink->xcontext->im_format)) {
/* This image is unusable. Destroying... */
- gst_buffer_unref (GST_BUFFER (xvimage));
+ gst_xvimage_buffer_free (xvimage);
xvimage = NULL;
} else {
/* We found a suitable image */
+ GST_DEBUG_OBJECT (xvimagesink, "found usable image in pool");
break;
}
}
/* Clear the xvimage */
if (xvimagesink->xvimage) {
- gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage));
+ gst_xvimage_buffer_free (xvimagesink->xvimage);
xvimagesink->xvimage = NULL;
}