ext/libvisual/visual.c: Cleanups, post nice errors.

Original commit message from CVS:
* ext/libvisual/visual.c: (gst_visual_init),
(gst_visual_clear_actors), (gst_visual_dispose),
(gst_visual_reset), (gst_visual_src_setcaps),
(gst_visual_sink_setcaps), (gst_vis_src_negotiate),
(gst_visual_sink_event), (gst_visual_src_event), (get_buffer),
(gst_visual_chain), (gst_visual_change_state):
Cleanups, post nice errors.
Handle sink and src events.
Implement simple QoS.
* gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init):
Use new basesink methods to configure max-lateness.
Small doc update.
* gst/ffmpegcolorspace/gstffmpegcolorspace.c:
(gst_ffmpegcsp_transform_caps), (gst_ffmpegcsp_set_caps):
Debug statement cleanups.
* gst/volume/gstvolume.c: (gst_volume_class_init):
Simple cleanup.
This commit is contained in:
Wim Taymans 2006-03-08 09:53:31 +00:00
parent 9a76cd88c1
commit 6b9594ac99
5 changed files with 221 additions and 65 deletions

View file

@ -1,3 +1,26 @@
2006-03-08 Wim Taymans <wim@fluendo.com>
* ext/libvisual/visual.c: (gst_visual_init),
(gst_visual_clear_actors), (gst_visual_dispose),
(gst_visual_reset), (gst_visual_src_setcaps),
(gst_visual_sink_setcaps), (gst_vis_src_negotiate),
(gst_visual_sink_event), (gst_visual_src_event), (get_buffer),
(gst_visual_chain), (gst_visual_change_state):
Cleanups, post nice errors.
Handle sink and src events.
Implement simple QoS.
* gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init):
Use new basesink methods to configure max-lateness.
Small doc update.
* gst/ffmpegcolorspace/gstffmpegcolorspace.c:
(gst_ffmpegcsp_transform_caps), (gst_ffmpegcsp_set_caps):
Debug statement cleanups.
* gst/volume/gstvolume.c: (gst_volume_class_init):
Simple cleanup.
2006-03-08 Tim-Philipp Müller <tim at centricular dot net>
* ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init),

View file

@ -62,10 +62,19 @@ struct _GstVisual
gint fps_d;
gint width;
gint height;
GstClockTime duration;
guint outsize;
/* samples per frame based on caps */
guint spf;
/* state stuff */
GstAdapter *adapter;
guint count;
/* QoS stuff *//* with LOCK */
gdouble proportion;
GstClockTime earliest_time;
};
struct _GstVisualClass
@ -109,6 +118,8 @@ static void gst_visual_dispose (GObject * object);
static GstStateChangeReturn gst_visual_change_state (GstElement * element,
GstStateChange transition);
static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer);
static gboolean gst_visual_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_visual_src_event (GstPad * pad, GstEvent * event);
static gboolean gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps);
static gboolean gst_visual_src_setcaps (GstPad * pad, GstCaps * caps);
@ -191,17 +202,31 @@ gst_visual_init (GstVisual * visual)
visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_sink_setcaps);
gst_pad_set_chain_function (visual->sinkpad, gst_visual_chain);
gst_pad_set_event_function (visual->sinkpad, gst_visual_sink_event);
gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad);
visual->srcpad = gst_pad_new_from_static_template (&src_template, "src");
gst_pad_set_setcaps_function (visual->srcpad, gst_visual_src_setcaps);
gst_pad_set_getcaps_function (visual->srcpad, gst_visual_getcaps);
gst_pad_set_event_function (visual->srcpad, gst_visual_src_event);
gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad);
visual->next_ts = 0;
visual->adapter = gst_adapter_new ();
}
static void
gst_visual_clear_actors (GstVisual * visual)
{
if (visual->actor) {
visual_object_unref (VISUAL_OBJECT (visual->actor));
visual->actor = NULL;
}
if (visual->video) {
visual_object_unref (VISUAL_OBJECT (visual->video));
visual->video = NULL;
}
}
static void
gst_visual_dispose (GObject * object)
{
@ -211,19 +236,23 @@ gst_visual_dispose (GObject * object)
g_object_unref (visual->adapter);
visual->adapter = NULL;
}
gst_visual_clear_actors (visual);
if (visual->actor) {
visual_object_unref (VISUAL_OBJECT (visual->actor));
visual->actor = NULL;
}
if (visual->video) {
visual_object_unref (VISUAL_OBJECT (visual->video));
visual->video = NULL;
}
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
}
static void
gst_visual_reset (GstVisual * visual)
{
visual->next_ts = -1;
gst_adapter_clear (visual->adapter);
GST_OBJECT_LOCK (visual);
visual->proportion = 1.0;
visual->earliest_time = -1;
GST_OBJECT_UNLOCK (visual);
}
static GstCaps *
gst_visual_getcaps (GstPad * pad)
{
@ -296,6 +325,15 @@ gst_visual_src_setcaps (GstPad * pad, GstCaps * caps)
visual_video_set_dimension (visual->video, visual->width, visual->height);
visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE);
/* precalc some values */
visual->outsize =
visual->video->height * GST_ROUND_UP_4 (visual->video->width) *
visual->video->bpp;
visual->spf =
gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
visual->duration =
gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n);
gst_object_unref (visual);
return TRUE;
@ -316,6 +354,11 @@ gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps)
gst_structure_get_int (structure, "rate", &visual->rate);
if (visual->fps_n != 0) {
visual->spf =
gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n);
}
gst_object_unref (visual);
return TRUE;
}
@ -356,12 +399,74 @@ gst_vis_src_negotiate (GstVisual * visual)
no_format:
{
GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL),
("could not negotiate output format"));
gst_caps_unref (intersect);
gst_caps_unref (othercaps);
return FALSE;
}
}
static gboolean
gst_visual_sink_event (GstPad * pad, GstEvent * event)
{
GstVisual *visual;
gboolean res;
visual = GST_VISUAL (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_FLUSH_START:
res = gst_pad_push_event (visual->srcpad, event);
break;
case GST_EVENT_FLUSH_STOP:
/* reset QoS and adapter. */
gst_visual_reset (visual);
res = gst_pad_push_event (visual->srcpad, event);
break;
default:
res = gst_pad_push_event (visual->srcpad, event);
break;
}
gst_object_unref (visual);
return res;
}
static gboolean
gst_visual_src_event (GstPad * pad, GstEvent * event)
{
GstVisual *visual;
gboolean res;
visual = GST_VISUAL (gst_pad_get_parent (pad));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_QOS:
{
gdouble proportion;
GstClockTimeDiff diff;
GstClockTime timestamp;
gst_event_parse_qos (event, &proportion, &diff, &timestamp);
GST_OBJECT_LOCK (visual);
visual->proportion = proportion;
visual->earliest_time = timestamp + diff;
GST_OBJECT_UNLOCK (visual);
res = gst_pad_push_event (visual->sinkpad, event);
break;
}
default:
res = gst_pad_push_event (visual->sinkpad, event);
break;
}
gst_object_unref (visual);
return res;
}
static GstFlowReturn
get_buffer (GstVisual * visual, GstBuffer ** outbuf)
{
@ -377,9 +482,8 @@ get_buffer (GstVisual * visual, GstBuffer ** outbuf)
ret =
gst_pad_alloc_buffer_and_set_caps (visual->srcpad,
GST_BUFFER_OFFSET_NONE,
visual->video->height * GST_ROUND_UP_4 (visual->video->width) *
visual->video->bpp, GST_PAD_CAPS (visual->srcpad), outbuf);
GST_BUFFER_OFFSET_NONE, visual->outsize,
GST_PAD_CAPS (visual->srcpad), outbuf);
if (ret != GST_FLOW_OK)
return ret;
@ -397,7 +501,6 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
guint i;
GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad));
GstFlowReturn ret = GST_FLOW_OK;
guint spf;
GST_DEBUG_OBJECT (visual, "chain function called");
@ -415,15 +518,33 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
if (GST_BUFFER_TIMESTAMP (buffer) != GST_CLOCK_TIME_NONE)
visual->next_ts = GST_BUFFER_TIMESTAMP (buffer);
/* spf = samples per frame */
spf = ((guint64) (visual->rate) * visual->fps_d) / visual->fps_n;
gst_adapter_push (visual->adapter, buffer);
while (gst_adapter_available (visual->adapter) > MAX (512, spf) * 4 &&
while (gst_adapter_available (visual->adapter) > MAX (512, visual->spf) * 4 &&
(ret == GST_FLOW_OK)) {
gboolean need_skip;
/* Read 512 samples per channel */
const guint16 *data =
(const guint16 *) gst_adapter_peek (visual->adapter, 512 * 4);
const guint16 *data;
data = (const guint16 *) gst_adapter_peek (visual->adapter, 512 * 4);
GST_DEBUG_OBJECT (visual, "QoS: in: %" G_GUINT64_FORMAT
", earliest: %" G_GUINT64_FORMAT, visual->next_ts,
visual->earliest_time);
if (visual->next_ts != -1) {
GST_OBJECT_LOCK (visual);
/* check for QoS, don't compute buffers that are known to be latea */
need_skip = visual->earliest_time != -1 &&
visual->next_ts <= visual->earliest_time;
GST_OBJECT_UNLOCK (visual);
if (need_skip) {
GST_WARNING_OBJECT (visual, "skipping frame because of QoS");
goto skip;
}
}
for (i = 0; i < 512; i++) {
visual->audio.plugpcm[0][i] = *data++;
@ -436,33 +557,29 @@ gst_visual_chain (GstPad * pad, GstBuffer * buffer)
goto beach;
}
}
visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf));
visual_audio_analyze (&visual->audio);
visual_actor_run (visual->actor, &visual->audio);
visual_video_set_buffer (visual->video, NULL);
if (visual->video != NULL) {
visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf));
visual_audio_analyze (&visual->audio);
visual_actor_run (visual->actor, &visual->audio);
GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
GST_BUFFER_DURATION (outbuf) = visual->duration;
GST_BUFFER_TIMESTAMP (outbuf) = visual->next_ts;
GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (GST_SECOND,
visual->fps_d, visual->fps_n);
visual->next_ts += GST_BUFFER_DURATION (outbuf);
ret = gst_pad_push (visual->srcpad, outbuf);
outbuf = NULL;
}
ret = gst_pad_push (visual->srcpad, outbuf);
outbuf = NULL;
GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
visual->spf);
skip:
/* interpollate next timestamp */
if (visual->next_ts != -1)
visual->next_ts += visual->duration;
/* Flush out the number of samples per frame * channels * sizeof (gint16) */
/* Recompute spf in case caps changed */
spf = ((guint64) (visual->rate) * visual->fps_d) / visual->fps_n;
GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input",
spf);
gst_adapter_flush (visual->adapter,
MIN (gst_adapter_available (visual->adapter), spf * 4));
MIN (gst_adapter_available (visual->adapter), visual->spf * 4));
}
/* so we're on the safe side */
if (visual->video)
visual_video_set_buffer (visual->video, NULL);
if (outbuf != NULL)
gst_buffer_unref (outbuf);
@ -485,18 +602,17 @@ gst_visual_change_state (GstElement * element, GstStateChange transition)
plugname);
visual->video = visual_video_new ();
/* can't have a play without actors */
if (!visual->actor || !visual->video)
return GST_STATE_CHANGE_FAILURE;
goto no_actors;
if (visual_actor_realize (visual->actor) != 0)
goto no_realize;
if (visual_actor_realize (visual->actor) != 0) {
visual_object_unref (VISUAL_OBJECT (visual->actor));
visual->actor = NULL;
return GST_STATE_CHANGE_FAILURE;
}
visual_actor_set_video (visual->actor, visual->video);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
gst_adapter_clear (visual->adapter);
gst_visual_reset (visual);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@ -510,21 +626,31 @@ gst_visual_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
visual->next_ts = 0;
break;
case GST_STATE_CHANGE_READY_TO_NULL:
if (visual->actor)
visual_object_unref (VISUAL_OBJECT (visual->actor));
if (visual->video)
visual_object_unref (VISUAL_OBJECT (visual->video));
visual->actor = NULL;
visual->video = NULL;
gst_visual_clear_actors (visual);
break;
default:
break;
}
return ret;
/* ERRORS */
no_actors:
{
GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
("could not create actors"));
gst_visual_clear_actors (visual);
return GST_STATE_CHANGE_FAILURE;
}
no_realize:
{
GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL),
("could not realize actor"));
gst_visual_clear_actors (visual);
return GST_STATE_CHANGE_FAILURE;
}
}
static void

View file

@ -25,8 +25,12 @@
*
* <refsect2>
* <para>
* Provides useful functions and a base class for video sinks. Right now it's
* mostly used as a place holder for adding common code later on.
* Provides useful functions and a base class for video sinks.
* </para>
* <para>
* GstVideoSink will configure the default base sink to drop frames that
* arrive later than 20ms as this is considered the default threshold for
* observing out-of-sync frames.
* </para>
* </refsect2>
*/
@ -99,7 +103,8 @@ gst_video_sink_init (GstVideoSink * videosink)
{
videosink->width = 0;
videosink->height = 0;
GST_BASE_SINK (videosink)->abidata.ABI.max_lateness = 20 * GST_MSECOND;
gst_base_sink_set_max_lateness (GST_BASE_SINK (videosink), 20 * GST_MSECOND);
}
static void

View file

@ -154,6 +154,7 @@ gst_ffmpegcsp_transform_caps (GstBaseTransform * btrans,
GST_DEBUG_OBJECT (btrans, "transformed %" GST_PTR_FORMAT " into %"
GST_PTR_FORMAT, caps, result);
return result;
}
@ -251,28 +252,28 @@ gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
/* ERRORS */
no_width_height:
{
GST_DEBUG ("did not specify width or height");
GST_DEBUG_OBJECT (space, "did not specify width or height");
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;
return FALSE;
}
no_framerate:
{
GST_DEBUG ("did not specify framerate");
GST_DEBUG_OBJECT (space, "did not specify framerate");
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;
return FALSE;
}
format_mismatch:
{
GST_DEBUG ("input and output formats do not match");
GST_DEBUG_OBJECT (space, "input and output formats do not match");
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;
return FALSE;
}
invalid_in_caps:
{
GST_DEBUG ("could not configure context for input format");
GST_DEBUG_OBJECT (space, "could not configure context for input format");
av_free (ctx);
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;
@ -280,7 +281,7 @@ invalid_in_caps:
}
invalid_out_caps:
{
GST_DEBUG ("could not configure context for output format");
GST_DEBUG_OBJECT (space, "could not configure context for output format");
av_free (ctx);
space->from_pixfmt = PIX_FMT_NB;
space->to_pixfmt = PIX_FMT_NB;

View file

@ -278,8 +278,11 @@ static void
gst_volume_class_init (GstVolumeClass * klass)
{
GObjectClass *gobject_class;
GstBaseTransformClass *trans_class;
gobject_class = (GObjectClass *) klass;
trans_class = (GstBaseTransformClass *) klass;
gobject_class->set_property = volume_set_property;
gobject_class->get_property = volume_get_property;
gobject_class->dispose = gst_volume_dispose;
@ -293,10 +296,8 @@ gst_volume_class_init (GstVolumeClass * klass)
0.0, VOLUME_MAX_DOUBLE, 1.0,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE));
GST_BASE_TRANSFORM_CLASS (klass)->transform_ip =
GST_DEBUG_FUNCPTR (volume_transform_ip);
GST_BASE_TRANSFORM_CLASS (klass)->set_caps =
GST_DEBUG_FUNCPTR (volume_set_caps);
trans_class->transform_ip = GST_DEBUG_FUNCPTR (volume_transform_ip);
trans_class->set_caps = GST_DEBUG_FUNCPTR (volume_set_caps);
}
static void