CVS Root: /cvs/gstreamer
Module: gst-plugins-base
Changes by: wtay
Date: Thu Mar 02 2006 16:47:46 UTC
Log message:
* docs/libs/gst-plugins-base-libs-docs.sgml:
* docs/libs/gst-plugins-base-libs-sections.txt:
* docs/libs/gst-plugins-base-libs.types:
* docs/plugins/Makefile.am:
* docs/plugins/gst-plugins-base-plugins-docs.sgml:
* docs/plugins/gst-plugins-base-plugins-sections.txt:
Added some more docs to libs and plugins.
* gst-libs/gst/audio/gstringbuffer.c:
(gst_ring_buffer_prepare_read), (gst_ring_buffer_clear):
* gst-libs/gst/audio/gstringbuffer.h:
Document ringbuffer some more.
* gst/videorate/gstvideorate.c: (gst_video_rate_class_init),
(gst_video_rate_setcaps), (gst_video_rate_reset),
(gst_video_rate_init), (gst_video_rate_flush_prev),
(gst_video_rate_swap_prev), (gst_video_rate_event),
(gst_video_rate_chain), (gst_video_rate_change_state):
* gst/videorate/gstvideorate.h:
Fix videorate to use segments.
Make it work with 0/1 framerates (closes #331903)
Handle EOS correctly.
Added docs.
Modified files:
. : ChangeLog
docs/libs : gst-plugins-base-libs-docs.sgml
gst-plugins-base-libs-sections.txt
gst-plugins-base-libs.types
docs/plugins : Makefile.am gst-plugins-base-plugins-docs.sgml
gst-plugins-base-plugins-sections.txt
gst-libs/gst/audio: gstringbuffer.c gstringbuffer.h
gst/videorate : gstvideorate.c
Added files:
gst/videorate : gstvideorate.h
Links:
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ChangeLog.diff?r1=1.2438&r2=1.2439
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs-docs.sgml.diff?r1=1.10&r2=1.11
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs-sections.txt.diff?r1=1.11&r2=1.12
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs.types.diff?r1=1.3&r2=1.4
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/plugins/Makefile.am.diff?r1=1.21&r2=1.22
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/plugins/gst-plugins-base-plugins-docs.sgml.diff?r1=1.19&r2=1.20
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/docs/plugins/gst-plugins-base-plugins-sections.txt.diff?r1=1.16&r2=1.17
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst-libs/gst/audio/gstringbuffer.c.diff?r1=1.37&r2=1.38
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst-libs/gst/audio/gstringbuffer.h.diff?r1=1.17&r2=1.18
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst/videorate/gstvideorate.c.diff?r1=1.32&r2=1.33
http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst/videorate/gstvideorate.h?rev=1.1&content-type=text/vnd.viewcvs-markup
====Begin Diffs====
Index: ChangeLog
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-base/ChangeLog,v
retrieving revision 1.2438
retrieving revision 1.2439
diff -u -d -r1.2438 -r1.2439
--- ChangeLog 2 Mar 2006 13:13:00 -0000 1.2438
+++ ChangeLog 2 Mar 2006 16:47:33 -0000 1.2439
@@ -1,3 +1,29 @@
+2006-03-02 Wim Taymans <wim@...>
+
+ * docs/libs/gst-plugins-base-libs-docs.sgml:
+ * docs/libs/gst-plugins-base-libs-sections.txt:
+ * docs/libs/gst-plugins-base-libs.types:
+ * docs/plugins/Makefile.am:
+ * docs/plugins/gst-plugins-base-plugins-docs.sgml:
+ * docs/plugins/gst-plugins-base-plugins-sections.txt:
+ Added some more docs to libs and plugins.
+ * gst-libs/gst/audio/gstringbuffer.c:
+ (gst_ring_buffer_prepare_read), (gst_ring_buffer_clear):
+ * gst-libs/gst/audio/gstringbuffer.h:
+ Document ringbuffer some more.
+ * gst/videorate/gstvideorate.c: (gst_video_rate_class_init),
+ (gst_video_rate_setcaps), (gst_video_rate_reset),
+ (gst_video_rate_init), (gst_video_rate_flush_prev),
+ (gst_video_rate_swap_prev), (gst_video_rate_event),
+ (gst_video_rate_chain), (gst_video_rate_change_state):
+ * gst/videorate/gstvideorate.h:
+ Fix videorate to use segments.
+ Make it work with 0/1 framerates (closes #331903)
+ Handle EOS correctly.
+ Added docs.
2006-03-02 Tim-Philipp Müller <tim at centricular dot net>
* ext/ogg/gstogmparse.c: (gst_ogm_parse_class_init),
Index: gst-plugins-base-libs-docs.sgml
RCS file: /cvs/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs-docs.sgml,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- gst-plugins-base-libs-docs.sgml 5 Feb 2006 18:22:01 -0000 1.10
+++ gst-plugins-base-libs-docs.sgml 2 Mar 2006 16:47:33 -0000 1.11
@@ -7,6 +7,8 @@
<!ENTITY GstCompiling SYSTEM "compiling.sgml">
<!ENTITY GstAudio SYSTEM "xml/gstaudio.xml">
<!ENTITY GstAudioMixerUtils SYSTEM "xml/gstaudiomixerutils.xml">
+<!ENTITY GstAudioSink SYSTEM "xml/gstaudiosink.xml">
+<!ENTITY GstBaseAudioSink SYSTEM "xml/gstbaseaudiosink.xml">
<!ENTITY GstCddaBaseSrc SYSTEM "xml/gstcddabasesrc.xml">
<!ENTITY GstVideoSink SYSTEM "xml/gstvideosink.xml">
<!ENTITY GstVideoFilter SYSTEM "xml/gstvideofilter.xml">
@@ -43,6 +45,8 @@
</para>
&GstAudio;
&GstAudioMixerUtils;
+ &GstBaseAudioSink;
+ &GstAudioSink;
&GstRingBuffer;
</chapter>
Index: gst-plugins-base-libs-sections.txt
RCS file: /cvs/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs-sections.txt,v
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- gst-plugins-base-libs-sections.txt 5 Feb 2006 18:22:01 -0000 1.11
+++ gst-plugins-base-libs-sections.txt 2 Mar 2006 16:47:33 -0000 1.12
@@ -17,6 +17,32 @@
</SECTION>
<SECTION>
+<FILE>gstaudiosink</FILE>
+<INCLUDE>gst/audio/gstaudiosink.h</INCLUDE>
+GstAudioSink
+GstAudioSinkClass
+</SECTION>
+<SECTION>
+<FILE>gstbaseaudiosink</FILE>
+<INCLUDE>gst/audio/gstbaseaudiosink.h</INCLUDE>
+GstBaseAudioSink
+GstBaseAudioSinkClass
+GST_BASE_AUDIO_SINK_CLOCK
+GST_BASE_AUDIO_SINK_PAD
+gst_base_audio_sink_create_ringbuffer
+<SUBSECTION Standard>
+GST_BASE_AUDIO_SINK
+GST_IS_BASE_AUDIO_SINK
+GST_TYPE_BASE_AUDIO_SINK
+gst_base_audio_sink_get_type
+GST_BASE_AUDIO_SINK_CLASS
+GST_IS_BASE_AUDIO_SINK_CLASS
+GST_BASE_AUDIO_SINK_GET_CLASS
<FILE>gstcddabasesrc</FILE>
<INCLUDE>gst/cdda/gstcddabasesrc.h</INCLUDE>
GstCddaBaseSrc
@@ -68,6 +94,7 @@
<FILE>gstringbuffer</FILE>
<INCLUDE>gst/audio/gstringbuffer.h</INCLUDE>
GstRingBuffer
+GstRingBufferSpec
GstRingBufferClass
gst_ring_buffer_set_callback
Index: gst-plugins-base-libs.types
RCS file: /cvs/gstreamer/gst-plugins-base/docs/libs/gst-plugins-base-libs.types,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- gst-plugins-base-libs.types 28 Dec 2005 18:19:25 -0000 1.3
+++ gst-plugins-base-libs.types 2 Mar 2006 16:47:33 -0000 1.4
@@ -1,12 +1,17 @@
#include <gst/gst.h>
#include <gst/interfaces/colorbalance.h>
-#include <gst/audio/gstringbuffer.h>
+gst_color_balance_get_type
+gst_color_balance_channel_get_type
+#include <gst/audio/gstringbuffer.h>
gst_ring_buffer_get_type
-gst_color_balance_get_type
-gst_color_balance_channel_get_type
+#include <gst/audio/gstaudiosink.h>
+gst_audio_sink_get_type
+#include <gst/audio/gstbaseaudiosink.h>
#include <gst/cdda/gstcddabasesrc.h>
gst_cdda_base_src_get_type
Index: Makefile.am
RCS file: /cvs/gstreamer/gst-plugins-base/docs/plugins/Makefile.am,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- Makefile.am 1 Mar 2006 18:25:18 -0000 1.21
+++ Makefile.am 2 Mar 2006 16:47:33 -0000 1.22
@@ -93,6 +93,7 @@
$(top_srcdir)/gst/ffmpegcolorspace/gstffmpegcolorspace.h \
$(top_srcdir)/gst/tcp/gstmultifdsink.h \
$(top_srcdir)/gst/tcp/gsttcpserversink.h \
+ $(top_srcdir)/gst/videorate/gstvideorate.h \
$(top_srcdir)/gst/videotestsrc/gstvideotestsrc.h \
$(top_srcdir)/gst/volume/gstvolume.h \
$(top_srcdir)/sys/ximage/ximagesink.h \
Index: gst-plugins-base-plugins-docs.sgml
RCS file: /cvs/gstreamer/gst-plugins-base/docs/plugins/gst-plugins-base-plugins-docs.sgml,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -d -r1.19 -r1.20
--- gst-plugins-base-plugins-docs.sgml 2 Mar 2006 11:28:23 -0000 1.19
+++ gst-plugins-base-plugins-docs.sgml 2 Mar 2006 16:47:33 -0000 1.20
@@ -28,6 +28,7 @@
<xi:include href="xml/element-textoverlay.xml" />
<xi:include href="xml/element-textrender.xml" />
<xi:include href="xml/element-timeoverlay.xml" />
+ <xi:include href="xml/element-videorate.xml" />
<xi:include href="xml/element-videotestsrc.xml" />
<xi:include href="xml/element-volume.xml" />
<xi:include href="xml/element-vorbisdec.xml" />
Index: gst-plugins-base-plugins-sections.txt
RCS file: /cvs/gstreamer/gst-plugins-base/docs/plugins/gst-plugins-base-plugins-sections.txt,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- gst-plugins-base-plugins-sections.txt 1 Mar 2006 18:25:18 -0000 1.16
+++ gst-plugins-base-plugins-sections.txt 2 Mar 2006 16:47:33 -0000 1.17
@@ -250,6 +250,19 @@
+<FILE>element-videorate</FILE>
+<TITLE>videorate</TITLE>
+GstVideoRate
+GstVideoRateClass
+GST_VIDEO_RATE
+GST_IS_VIDEO_RATE
+GST_TYPE_VIDEO_RATE
+GST_VIDEO_RATE_CLASS
+GST_IS_VIDEO_RATE_CLASS
<FILE>element-videotestsrc</FILE>
<TITLE>videotestsrc</TITLE>
GstVideoTestSrc
Index: gstringbuffer.c
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/audio/gstringbuffer.c,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- gstringbuffer.c 17 Feb 2006 14:07:01 -0000 1.37
+++ gstringbuffer.c 2 Mar 2006 16:47:33 -0000 1.38
@@ -21,11 +21,23 @@
/**
* SECTION:gstringbuffer
* @short_description: Base class for audio ringbuffer implementations
+ * @see_also: gstbaseaudiosink
*
+ * <refsect2>
+ * <para>
* This object is the base class for audio ringbuffers used by the base
* audio source and sink classes.
+ * </para>
+ * The ringbuffer abstracts a circular buffer of data. One reader and
+ * one writer can operate on the data from different threads in a lockfree
+ * manner. The base class is sufficiently flexible to be used as an
+ * abstraction for DMA based ringbuffers as well as a pure software
+ * implementations.
+ * </refsect2>
- * Last reviewed on 2005-11-24 (0.9.6)
+ * Last reviewed on 2006-02-02 (0.10.4)
*/
#include <string.h>
@@ -1121,7 +1133,7 @@
* @buf. The first sample should be written at position @sample in
* the ringbuffer.
- * @len not needs to be a multiple of the segment size of the ringbuffer
+ * @len does not need to be a multiple of the segment size of the ringbuffer
* although it is recommended for optimal performance.
* Returns: The number of samples written to the ringbuffer or -1 on
@@ -1336,7 +1348,7 @@
* @len: the number of bytes to read
* Returns a pointer to memory where the data from segment @segment
- * can be found. This function is used by subclasses.
+ * can be found. This function is mostly used by subclasses.
* Returns: FALSE if the buffer is not started.
@@ -1349,11 +1361,12 @@
guint8 *data;
gint segdone;
+ g_return_val_if_fail (buf != NULL, FALSE);
/* buffer must be started */
if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED)
return FALSE;
- g_return_val_if_fail (buf != NULL, FALSE);
g_return_val_if_fail (buf->data != NULL, FALSE);
g_return_val_if_fail (segment != NULL, FALSE);
g_return_val_if_fail (readptr != NULL, FALSE);
@@ -1429,7 +1442,9 @@
if (G_UNLIKELY (buf->data == NULL))
return;
- g_return_if_fail (buf->empty_seg != NULL);
+ /* no empty_seg means it's not opened */
+ if (G_UNLIKELY (buf->empty_seg == NULL))
+ return;
segment %= buf->spec.segtotal;
Index: gstringbuffer.h
RCS file: /cvs/gstreamer/gst-plugins-base/gst-libs/gst/audio/gstringbuffer.h,v
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- gstringbuffer.h 10 Jan 2006 09:38:44 -0000 1.17
+++ gstringbuffer.h 2 Mar 2006 16:47:33 -0000 1.18
@@ -199,6 +199,23 @@
#define GST_RING_BUFFER_SIGNAL(buf) (g_cond_signal (GST_RING_BUFFER_GET_COND (buf)))
#define GST_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_RING_BUFFER_GET_COND (buf)))
+/**
+ * GstRingBuffer:
+ * @cond: used to signal start/stop/pause/resume actions
+ * @open: boolean indicating that the ringbuffer is open
+ * @acquired: boolean indicating that the ringbuffer is acquired
+ * @data: data in the ringbuffer
+ * @spec: format and layout of the ringbuffer data
+ * @segstate: status of each segment in the ringbuffer (unused)
+ * @samples_per_seg: number of samples in one segment
+ * @empty_seg: pointer to memory holding one segment of silence samples
+ * @state: state of the buffer
+ * @segdone: readpointer in the ringbuffer
+ * @segbase: segment corresponding to segment 0 (unused)
+ * @waiting: is a reader or writer waiting for a free segment
+ *
+ * The ringbuffer base class structure.
+ */
struct _GstRingBuffer {
GstObject object;
@@ -209,14 +226,14 @@
GstBuffer *data;
GstRingBufferSpec spec;
GstRingBufferSegState *segstate;
- gint samples_per_seg; /* number of samples per segment */
+ gint samples_per_seg;
guint8 *empty_seg;
/*< public >*/ /* ATOMIC */
- gint state; /* state of the buffer */
- gint segdone; /* number of segments processed since last start */
- gint segbase; /* segment corresponding to segment 0 */
- gint waiting; /* when waiting for a segment to be freed */
+ gint state;
+ gint segdone;
+ gint segbase;
+ gint waiting;
/*< private >*/
GstRingBufferCallback callback;
@@ -232,26 +249,34 @@
} abidata;
};
+ * GstRingBufferClass:
+ * @open_device: open the device, don't set any params or allocate anything
+ * @acquire: allocate the resources for the ringbuffer using the given spec
+ * @release: free resources of the ringbuffer
+ * @close_device: close the device
+ * @start: start processing of samples
+ * @pause: pause processing of samples
+ * @resume: resume processing of samples after pause
+ * @stop: stop processing of samples
+ * @delay: get number of samples queued in device
+ * The vmethods that subclasses can override to implement the ringbuffer.
struct _GstRingBufferClass {
GstObjectClass parent_class;
/*< public >*/
- /* just open the device, don't set any params or allocate anything */
gboolean (*open_device) (GstRingBuffer *buf);
- /* allocate the resources for the ringbuffer using the given specs */
gboolean (*acquire) (GstRingBuffer *buf, GstRingBufferSpec *spec);
- /* free resources of the ringbuffer */
gboolean (*release) (GstRingBuffer *buf);
- /* close the device */
gboolean (*close_device) (GstRingBuffer *buf);
- /* playback control */
gboolean (*start) (GstRingBuffer *buf);
gboolean (*pause) (GstRingBuffer *buf);
gboolean (*resume) (GstRingBuffer *buf);
gboolean (*stop) (GstRingBuffer *buf);
- /* number of samples queued in device */
guint (*delay) (GstRingBuffer *buf);
Index: gstvideorate.c
RCS file: /cvs/gstreamer/gst-plugins-base/gst/videorate/gstvideorate.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -d -r1.32 -r1.33
--- gstvideorate.c 29 Jan 2006 19:13:39 -0000 1.32
+++ gstvideorate.c 2 Mar 2006 16:47:34 -0000 1.33
@@ -17,57 +17,56 @@
* Boston, MA 02111-1307, USA.
+ * SECTION:element-videorate
+ * @short_description: adjusts the framerate of video
+ * This element converts video from one framerate to another. This operation
+ * is performed by dropping and duplicating frames, no fance algorithm is
+ * used to interpolate frames (yet).
+ * By default the element will simply negotiate the same framerate on its source and
+ * sink pad and will adjust timestamps/insert/drop frames in case the input stream
+ * is not respecting that framerate.
+ * A conversion to another framerate can be forced by using filtered caps on the source
+ * pad.
+ * The properties "in", "out", "duplicate" and "drop" can be read to obtain
+ * information about respectively received frame, outputed frame, duplicated frames
+ * and dropped frames.
+ * When the "silent" property is set to FALSE, a GObject property notification will
+ * be emited whenever one of the "duplicate" or "drop" values changed. This can
+ * potentially cause performance degradation. Also note that property notification
+ * will happen in the streaming thread so applications should be prepared for this.
+ * <title>Example pipelines</title>
+ * <programlisting>
+ * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videorate ! video/x-raw-yuv,framerate=15/1 ! xvimagesink
+ * </programlisting>
+ * Decode an Ogg/Theora and adjust the framerate to 15 fps.
+ * To create the test Ogg/Theora file refer to the documentation of theoraenc.
+ * Last reviewed on 2006-03-02 (0.10.4)
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
-#include <gst/gst.h>
+#include "gstvideorate.h"
GST_DEBUG_CATEGORY (video_rate_debug);
#define GST_CAT_DEFAULT video_rate_debug
-#define GST_TYPE_VIDEO_RATE \
- (gst_video_rate_get_type())
-#define GST_VIDEO_RATE(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_RATE,GstVideoRate))
-#define GST_VIDEO_RATE_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_RATE,GstVideoRate))
-#define GST_IS_VIDEO_RATE(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_RATE))
-#define GST_IS_VIDEO_RATE_CLASS(obj) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_RATE))
-
-typedef struct _GstVideoRate GstVideoRate;
-typedef struct _GstVideoRateClass GstVideoRateClass;
-struct _GstVideoRate
-{
- GstElement element;
- GstPad *sinkpad, *srcpad;
- /* video state */
- gint from_rate_numerator, from_rate_denominator;
- gint to_rate_numerator, to_rate_denominator;
- guint64 next_ts; /* Timestamp of next buffer to output */
- GstBuffer *prevbuf;
- guint64 prev_ts; /* Previous buffer timestamp */
- guint64 in, out, dup, drop;
- /* segment handling */
- gint64 segment_start;
- gint64 segment_stop;
- gint64 segment_accum;
- gboolean silent;
- gdouble new_pref;
-};
-struct _GstVideoRateClass
- GstElementClass parent_class;
/* elementfactory information */
static GstElementDetails video_rate_details =
GST_ELEMENT_DETAILS ("Video rate adjuster",
@@ -114,6 +113,9 @@
static void gst_video_rate_base_init (gpointer g_class);
static void gst_video_rate_class_init (GstVideoRateClass * klass);
static void gst_video_rate_init (GstVideoRate * videorate);
+static void gst_video_rate_swap_prev (GstVideoRate * videorate,
+ GstBuffer * buffer, gint64 time);
static gboolean gst_video_rate_event (GstPad * pad, GstEvent * event);
static GstFlowReturn gst_video_rate_chain (GstPad * pad, GstBuffer * buffer);
@@ -195,7 +197,7 @@
DEFAULT_SILENT, G_PARAM_READWRITE));
g_object_class_install_property (object_class, ARG_NEW_PREF,
g_param_spec_double ("new_pref", "New Pref",
- "Value indicating how much to prefer new frames",
+ "Value indicating how much to prefer new frames (unused)",
0.0, 1.0, DEFAULT_NEW_PREF, G_PARAM_READWRITE));
element_class->change_state = gst_video_rate_change_state;
@@ -264,12 +266,12 @@
GstPad *otherpad, *opeer;
gint rate_numerator, rate_denominator;
- videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad));
+ videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad));
structure = gst_caps_get_structure (caps, 0);
if (!gst_structure_get_fraction (structure, "framerate",
&rate_numerator, &rate_denominator))
- goto done;
+ goto no_framerate;
if (pad == videorate->srcpad) {
videorate->to_rate_numerator = rate_numerator;
@@ -297,7 +299,7 @@
/* see how we can transform the input caps */
if (!gst_video_rate_transformcaps (pad, caps, otherpad, &transform))
- goto done;
+ goto no_transform;
/* see what the peer can do */
peercaps = gst_pad_get_caps (opeer);
@@ -337,16 +339,26 @@
gst_object_unref (opeer);
}
done:
+ gst_object_unref (videorate);
return ret;
+no_framerate:
+ {
+ GST_DEBUG_OBJECT (videorate, "no framerate specified");
+ goto done;
+ }
+no_transform:
+ GST_DEBUG_OBJECT (videorate, "no framerate transform possible");
+ ret = FALSE;
}
static void
-gst_video_rate_blank_data (GstVideoRate * videorate)
+gst_video_rate_reset (GstVideoRate * videorate)
{
GST_DEBUG ("resetting data");
- if (videorate->prevbuf)
- gst_buffer_unref (videorate->prevbuf);
- videorate->prevbuf = NULL;
videorate->from_rate_numerator = 0;
videorate->from_rate_denominator = 0;
@@ -357,11 +369,9 @@
videorate->drop = 0;
videorate->dup = 0;
videorate->next_ts = G_GINT64_CONSTANT (0);
- videorate->prev_ts = G_GINT64_CONSTANT (0);
+ gst_video_rate_swap_prev (videorate, NULL, 0);
- videorate->segment_start = 0;
- videorate->segment_stop = 0;
- videorate->segment_accum = 0;
+ gst_segment_init (&videorate->segment, GST_FORMAT_TIME);
@@ -382,57 +392,125 @@
gst_pad_set_getcaps_function (videorate->srcpad, gst_video_rate_getcaps);
gst_pad_set_setcaps_function (videorate->srcpad, gst_video_rate_setcaps);
- gst_video_rate_blank_data (videorate);
+ gst_video_rate_reset (videorate);
videorate->silent = DEFAULT_SILENT;
videorate->new_pref = DEFAULT_NEW_PREF;
+/* flush the oldest buffer */
+static GstFlowReturn
+gst_video_rate_flush_prev (GstVideoRate * videorate)
+{
+ GstFlowReturn res;
+ GstBuffer *outbuf;
+ GstClockTime push_ts;
+ /* make sure we can write to the metadata */
+ outbuf =
+ gst_buffer_create_sub (videorate->prevbuf, 0,
+ GST_BUFFER_SIZE (videorate->prevbuf));
+ /* this is the timestamp we put on the buffer */
+ push_ts = videorate->next_ts;
+ GST_BUFFER_TIMESTAMP (outbuf) = push_ts;
+ videorate->out++;
+ if (videorate->to_rate_numerator) {
+ videorate->next_ts =
+ gst_util_uint64_scale (videorate->out,
+ videorate->to_rate_denominator * GST_SECOND,
+ videorate->to_rate_numerator);
+ GST_BUFFER_DURATION (outbuf) =
+ videorate->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
+ /* adapt for looping, bring back to time in current segment. */
+ GST_BUFFER_TIMESTAMP (outbuf) -= videorate->segment.accum;
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (videorate->srcpad));
+ GST_LOG_OBJECT (videorate,
+ "old is best, dup, pushing buffer outgoing ts %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (push_ts));
+ if ((res = gst_pad_push (videorate->srcpad, outbuf)) != GST_FLOW_OK)
+ goto push_error;
+ return res;
+ /* ERRORS */
+push_error:
+ GST_WARNING_OBJECT (videorate, "couldn't push buffer on srcpad, reason %s",
+ gst_flow_get_name (res));
+ return res;
+}
+static void
+gst_video_rate_swap_prev (GstVideoRate * videorate, GstBuffer * buffer,
+ gint64 time)
+ if (videorate->prevbuf)
+ gst_buffer_unref (videorate->prevbuf);
+ videorate->prevbuf = buffer;
+ videorate->prev_ts = time;
static GstFlowReturn
gst_video_rate_event (GstPad * pad, GstEvent * event)
GstVideoRate *videorate;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
{
- gint64 start, stop, base;
+ gint64 start, stop, time;
gdouble rate;
gboolean update;
GstFormat format;
gst_event_parse_new_segment (event, &update, &rate, &format, &start,
- &stop, &base);
+ &stop, &time);
- if (format != GST_FORMAT_TIME) {
- GST_WARNING ("Got discont but doesn't have GST_FORMAT_TIME value");
- } else {
- /*
- We just want to update the accumulated stream_time.
- */
- videorate->segment_accum +=
- videorate->segment_stop - videorate->segment_start;
- videorate->segment_start = start;
- videorate->segment_stop = stop;
- GST_DEBUG_OBJECT (videorate, "Updated segment_accum:%" GST_TIME_FORMAT
- " segment_start:%" GST_TIME_FORMAT " segment_stop:%"
- GST_TIME_FORMAT, GST_TIME_ARGS (videorate->segment_accum),
- GST_TIME_ARGS (videorate->segment_start),
- GST_TIME_ARGS (videorate->segment_stop));
- }
+ if (format != videorate->segment.format)
+ goto format_error;
+ /* We just want to update the accumulated stream_time */
+ gst_segment_set_newsegment (&videorate->segment, update, rate,
+ format, start, stop, time);
+ GST_DEBUG_OBJECT (videorate, "Updated segment.accum:%" GST_TIME_FORMAT
+ " segment.start:%" GST_TIME_FORMAT " segment.stop:%"
+ GST_TIME_FORMAT, GST_TIME_ARGS (videorate->segment.accum),
+ GST_TIME_ARGS (videorate->segment.start),
+ GST_TIME_ARGS (videorate->segment.stop));
break;
}
+ case GST_EVENT_EOS:
+ /* flush last queued frame */
+ gst_video_rate_flush_prev (videorate);
+ break;
case GST_EVENT_FLUSH_STOP:
- {
- gst_video_rate_blank_data (videorate);
- }
+ /* also resets the segment */
+ gst_video_rate_reset (videorate);
default:
+done:
return gst_pad_event_default (pad, event);
+format_error:
+ GST_WARNING_OBJECT (videorate,
+ "Got segment but doesn't have GST_FORMAT_TIME value");
@@ -440,31 +518,28 @@
GstFlowReturn res = GST_FLOW_OK;
+ GstClockTime intime;
- if (videorate->from_rate_numerator == 0 ||
- videorate->from_rate_denominator == 0 ||
- videorate->to_rate_denominator == 0 || videorate->to_rate_numerator == 0)
- return GST_FLOW_NOT_NEGOTIATED;
+ /* make sure the denominators have to be != 0 */
+ if (videorate->from_rate_denominator == 0 ||
+ videorate->to_rate_denominator == 0)
+ goto not_negotiated;
+ intime = gst_segment_to_running_time (&videorate->segment,
+ GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer));
/* pull in 2 buffers */
if (videorate->prevbuf == NULL) {
- /* We're sure it's a GstBuffer here */
- videorate->prevbuf = buffer;
- videorate->prev_ts =
- GST_BUFFER_TIMESTAMP (buffer) - videorate->segment_start +
- videorate->segment_accum;
+ gst_video_rate_swap_prev (videorate, buffer, intime);
videorate->next_ts = 0;
} else {
- GstClockTime prevtime, intime;
+ GstClockTime prevtime;
gint count = 0;
gint64 diff1, diff2;
prevtime = videorate->prev_ts;
- intime =
GST_LOG_OBJECT (videorate,
"BEGINNING prev buf %" GST_TIME_FORMAT " new buf %" GST_TIME_FORMAT
@@ -492,40 +567,11 @@
/* output first one when its the best */
if (diff1 < diff2) {
- GstBuffer *outbuf;
- GstClockTime push_ts;
count++;
- outbuf =
- gst_buffer_create_sub (videorate->prevbuf, 0,
- GST_BUFFER_SIZE (videorate->prevbuf));
- GST_BUFFER_TIMESTAMP (outbuf) = videorate->next_ts;
- push_ts = GST_BUFFER_TIMESTAMP (outbuf);
- videorate->out++;
- if (videorate->to_rate_numerator) {
- videorate->next_ts =
- gst_util_uint64_scale_int (videorate->out * GST_SECOND,
- videorate->to_rate_denominator, videorate->to_rate_numerator);
- GST_BUFFER_DURATION (outbuf) =
- videorate->next_ts - GST_BUFFER_TIMESTAMP (outbuf);
- }
- /* adapt for looping */
- GST_BUFFER_TIMESTAMP (outbuf) -= videorate->segment_accum;
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (videorate->srcpad));
- GST_LOG_OBJECT (videorate,
- "old is best, dup, pushing buffer outgoing ts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (push_ts));
- if ((res = gst_pad_push (videorate->srcpad, outbuf)) != GST_FLOW_OK) {
- GST_WARNING_OBJECT (videorate, "couldn't push buffer on srcpad:%d",
- res);
+ /* on error the _flush function posted a warning already */
+ if ((res = gst_video_rate_flush_prev (videorate)) != GST_FLOW_OK)
goto done;
- "old is best, dup, pushed buffer outgoing ts %" GST_TIME_FORMAT,
}
/* continue while the first one was the best */
@@ -540,8 +586,10 @@
/* if we didn't output the first buffer, we have a drop */
else if (count == 0) {
videorate->drop++;
if (!videorate->silent)
g_object_notify (G_OBJECT (videorate), "drop");
GST_LOG_OBJECT (videorate,
"new is best, old never used, drop, outgoing ts %"
GST_TIME_FORMAT, GST_TIME_ARGS (videorate->next_ts));
@@ -554,15 +602,19 @@
videorate->in, videorate->out, videorate->drop, videorate->dup);
/* swap in new one when it's the best */
return res;
+not_negotiated:
+ GST_WARNING_OBJECT (videorate, "no framerate negotiated");
+ res = GST_FLOW_NOT_NEGOTIATED;
@@ -632,7 +684,7 @@
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY:
--- NEW FILE: gstvideorate.h ---
/* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@...>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_VIDEO_RATE_H__
#define __GST_VIDEO_RATE_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_VIDEO_RATE \
(gst_video_rate_get_type())
#define GST_VIDEO_RATE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_RATE,GstVideoRate))
#define GST_VIDEO_RATE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_RATE,GstVideoRate))
#define GST_IS_VIDEO_RATE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_RATE))
#define GST_IS_VIDEO_RATE_CLASS(obj) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_RATE))
typedef struct _GstVideoRate GstVideoRate;
typedef struct _GstVideoRateClass GstVideoRateClass;
/**
* GstVideoRate:
* Opaque data structure.
struct _GstVideoRate
{
GstElement element;
GstPad *sinkpad, *srcpad;
/* video state */
gint from_rate_numerator, from_rate_denominator;
gint to_rate_numerator, to_rate_denominator;
guint64 next_ts; /* Timestamp of next buffer to output */
GstBuffer *prevbuf;
guint64 prev_ts; /* Previous buffer timestamp */
guint64 in, out, dup, drop;
/* segment handling */
GstSegment segment;
gboolean silent;
gdouble new_pref;
};
struct _GstVideoRateClass
GstElementClass parent_class;
G_END_DECLS
#endif /* __GST_VIDEO_RATE_H__ */
|