static GstStateChangeReturn gst_pulsesink_change_state (GstElement * element,
GstStateChange transition);
- #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
- # define FORMATS "{ S16LE, S16BE, F32LE, F32BE, S32LE, S32BE, " \
- "S24LE, S24BE, S24_32LE, S24_32BE, S8 }"
- #else
- # define FORMATS "{ S16BE, S16LE, F32BE, F32LE, S32BE, S32LE, " \
- "S24BE, S24LE, S24_32BE, S24_32LE, S8 }"
- #endif
-
-static void gst_pulsesink_init_interfaces (GType type);
+static GstStaticPadTemplate pad_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("audio/x-raw, "
- "format = (string) " FORMATS ", "
- "rate = (int) [ 1, MAX ], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-alaw, "
- "rate = (int) [ 1, MAX], "
- "channels = (int) [ 1, 32 ];"
- "audio/x-mulaw, "
- "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
- #ifdef HAVE_PULSE_1_0
- "audio/x-ac3, framed = (boolean) true;"
- "audio/x-eac3, framed = (boolean) true; "
- "audio/x-dts, framed = (boolean) true, "
- " block_size = (int) { 512, 1024, 2048 }; "
- "audio/mpeg, mpegversion = (int)1, "
- " mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true; "
- #endif
- ));
++ GST_STATIC_CAPS (PULSE_SINK_TEMPLATE_CAPS));
GST_IMPLEMENT_PULSEPROBE_METHODS (GstPulseSink, gst_pulsesink);
GType gst_pulsesink_get_type (void);
-# define ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN"
+ #if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
-# define ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN"
++# define FORMATS "{ S16LE, S16BE, F32LE, F32BE, S32LE, S32BE, " \
++ "S24LE, S24BE, S24_32LE, S24_32BE, S8 }"
+ #else
- "audio/x-raw-int, " \
- "endianness = (int) { " ENDIANNESS " }, " \
- "signed = (boolean) TRUE, " \
- "width = (int) 16, " \
- "depth = (int) 16, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, 32 ];" \
- "audio/x-raw-float, " \
- "endianness = (int) { " ENDIANNESS " }, " \
- "width = (int) 32, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, 32 ];" \
- "audio/x-raw-int, " \
- "endianness = (int) { " ENDIANNESS " }, " \
- "signed = (boolean) TRUE, " \
- "width = (int) 32, " \
- "depth = (int) 32, " \
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];" \
- "audio/x-raw-int, " \
- "signed = (boolean) FALSE, " \
- "width = (int) 8, " \
- "depth = (int) 8, " \
++# define FORMATS "{ S16BE, S16LE, F32BE, F32LE, S32BE, S32LE, " \
++ "S24BE, S24LE, S24_32BE, S24_32LE, S8 }"
+ #endif
+
+ #define _PULSE_SINK_CAPS_COMMON \
- "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];" \
- "audio/x-raw-int, " \
- "endianness = (int) { " ENDIANNESS " }, " \
- "signed = (boolean) TRUE, " \
- "width = (int) 24, " \
- "depth = (int) 24, " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, 32 ];" \
- "audio/x-raw-int, " \
- "endianness = (int) { " ENDIANNESS " }, " \
- "signed = (boolean) TRUE, " \
- "width = (int) 32, " \
- "depth = (int) 24, " \
- "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 32 ];"
++ "audio/x-raw, " \
++ "format = (string) " FORMATS ", " \
+ "rate = (int) [ 1, MAX ], " \
+ "channels = (int) [ 1, 32 ];" \
+ "audio/x-alaw, " \
+ "rate = (int) [ 1, MAX], " \
+ "channels = (int) [ 1, 32 ];" \
+ "audio/x-mulaw, " \
++ "rate = (int) [ 1, MAX], " "channels = (int) [ 1, 32 ];"
+
+ #ifdef HAVE_PULSE_1_0
+ #define _PULSE_SINK_CAPS_1_0 \
+ "audio/x-ac3, framed = (boolean) true;" \
+ "audio/x-eac3, framed = (boolean) true; " \
+ "audio/x-dts, framed = (boolean) true, " \
+ "block-size = (int) { 512, 1024, 2048 }; " \
+ "audio/mpeg, mpegversion = (int) 1, " \
+ "mpegaudioversion = (int) [ 1, 2 ], parsed = (boolean) true;"
+ #else
+ #define _PULSE_SINK_CAPS_1_0 ""
+ #endif
+
+ #define PULSE_SINK_TEMPLATE_CAPS \
+ _PULSE_SINK_CAPS_COMMON \
+ _PULSE_SINK_CAPS_1_0
+
+ #ifdef HAVE_PULSE_1_0
+
+ #define GST_TYPE_PULSE_AUDIO_SINK \
+ (gst_pulse_audio_sink_get_type())
+ #define GST_PULSE_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PULSE_AUDIO_SINK,GstPulseAudioSink))
+ #define GST_PULSE_AUDIO_SINK_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PULSE_AUDIO_SINK,GstPulseAudioSinkClass))
+ #define GST_IS_PULSE_AUDIO_SINK(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PULSE_AUDIO_SINK))
+ #define GST_IS_PULSE_AUDIO_SINK_CLASS(obj) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PULSE_AUDIO_SINK))
+ #define GST_PULSE_AUDIO_SINK_CAST(obj) \
+ ((GstPulseAudioSink *)(obj))
+
+ GType gst_pulse_audio_sink_get_type (void);
+
+ #endif /* HAVE_PULSE_1_0 */
+
G_END_DECLS
#endif /* __GST_PULSESINK_H__ */
/* class initialization */
- #define gst_soup_http_sink_parent_class parent_class
- G_DEFINE_TYPE (GstSoupHttpSink, gst_soup_http_sink, GST_TYPE_BASE_SINK);
-#define DEBUG_INIT(bla) \
- GST_DEBUG_CATEGORY_INIT (souphttpclientsink_dbg, "souphttpclientsink", 0, \
- "souphttpclientsink element");
-
-GST_BOILERPLATE_FULL (GstSoupHttpClientSink, gst_soup_http_client_sink,
- GstBaseSink, GST_TYPE_BASE_SINK, DEBUG_INIT);
-
-static void
-gst_soup_http_client_sink_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_soup_http_client_sink_sink_template));
-
- gst_element_class_set_details_simple (element_class, "HTTP client sink",
- "Generic", "Sends streams to HTTP server via PUT",
- "David Schleef <ds@entropywave.com>");
-}
++#define gst_soup_http_client_sink_parent_class parent_class
++G_DEFINE_TYPE (GstSoupHttpClientSink, gst_soup_http_client_sink,
++ GST_TYPE_BASE_SINK);
static void
- gst_soup_http_sink_class_init (GstSoupHttpSinkClass * klass)
+ gst_soup_http_client_sink_class_init (GstSoupHttpClientSinkClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
GstBaseSinkClass *base_sink_class = GST_BASE_SINK_CLASS (klass);
- gobject_class->set_property = gst_soup_http_sink_set_property;
- gobject_class->get_property = gst_soup_http_sink_get_property;
- gobject_class->dispose = gst_soup_http_sink_dispose;
- gobject_class->finalize = gst_soup_http_sink_finalize;
+ gobject_class->set_property = gst_soup_http_client_sink_set_property;
+ gobject_class->get_property = gst_soup_http_client_sink_get_property;
+ gobject_class->dispose = gst_soup_http_client_sink_dispose;
+ gobject_class->finalize = gst_soup_http_client_sink_finalize;
- base_sink_class->set_caps =
- GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_set_caps);
- if (0)
- base_sink_class->get_times =
- GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_get_times);
- base_sink_class->start = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_start);
- base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_stop);
- base_sink_class->unlock =
- GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_unlock);
- base_sink_class->event = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_event);
- if (0)
- base_sink_class->preroll =
- GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_preroll);
- base_sink_class->render =
- GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_render);
g_object_class_install_property (gobject_class,
PROP_LOCATION,
g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies",
G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- gst_static_pad_template_get (&gst_soup_http_sink_sink_template));
+ gst_element_class_add_pad_template (gstelement_class,
- base_sink_class->set_caps = GST_DEBUG_FUNCPTR (gst_soup_http_sink_set_caps);
++ gst_static_pad_template_get (&gst_soup_http_client_sink_sink_template));
+
+ gst_element_class_set_details_simple (gstelement_class, "HTTP client sink",
+ "Generic", "Sends streams to HTTP server via PUT",
+ "David Schleef <ds@entropywave.com>");
+
- GST_DEBUG_FUNCPTR (gst_soup_http_sink_get_times);
- base_sink_class->start = GST_DEBUG_FUNCPTR (gst_soup_http_sink_start);
- base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_soup_http_sink_stop);
- base_sink_class->unlock = GST_DEBUG_FUNCPTR (gst_soup_http_sink_unlock);
- base_sink_class->event = GST_DEBUG_FUNCPTR (gst_soup_http_sink_event);
++ base_sink_class->set_caps =
++ GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_set_caps);
+ if (0)
+ base_sink_class->get_times =
- base_sink_class->preroll = GST_DEBUG_FUNCPTR (gst_soup_http_sink_preroll);
- base_sink_class->render = GST_DEBUG_FUNCPTR (gst_soup_http_sink_render);
++ GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_get_times);
++ base_sink_class->start = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_start);
++ base_sink_class->stop = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_stop);
++ base_sink_class->unlock =
++ GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_unlock);
++ base_sink_class->event = GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_event);
+ if (0)
- GST_DEBUG_CATEGORY_INIT (gst_soup_http_sink_debug_category, "souphttpsink", 0,
- "debug category for souphttpsink element");
++ base_sink_class->preroll =
++ GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_preroll);
++ base_sink_class->render =
++ GST_DEBUG_FUNCPTR (gst_soup_http_client_sink_render);
++
++ GST_DEBUG_CATEGORY_INIT (souphttpclientsink_dbg, "souphttpclientsink", 0,
++ "souphttpclientsink element");
+
}
static void
- gst_soup_http_sink_init (GstSoupHttpSink * souphttpsink)
-gst_soup_http_client_sink_init (GstSoupHttpClientSink * souphttpsink,
- GstSoupHttpClientSinkClass * souphttpsink_class)
++gst_soup_http_client_sink_init (GstSoupHttpClientSink * souphttpsink)
{
const char *proxy;
GstBuffer *buf = gst_value_get_buffer (value);
if (buf) {
- const guint8 *buffer = GST_BUFFER_DATA (buf);
+ guint8 *data;
+ gsize size;
guint sr_idx;
- sr_idx = ((buffer[0] & 0x07) << 1) | ((buffer[1] & 0x80) >> 7);
- aacparse->object_type = (buffer[0] & 0xf8) >> 3;
+ data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
+ sr_idx = ((data[0] & 0x07) << 1) | ((data[1] & 0x80) >> 7);
+ aacparse->object_type = (data[0] & 0xf8) >> 3;
aacparse->sample_rate = gst_aac_parse_get_sample_rate_from_index (sr_idx);
- aacparse->channels = (buffer[1] & 0x78) >> 3;
+ aacparse->channels = (data[1] & 0x78) >> 3;
aacparse->header_type = DSPAAC_HEADER_NONE;
aacparse->mpegversion = 4;
- aacparse->frame_samples = (buffer[1] & 4) ? 960 : 1024;
++ aacparse->frame_samples = (data[1] & 4) ? 960 : 1024;
+ gst_buffer_unmap (buf, data, size);
- GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d",
- aacparse->object_type, aacparse->sample_rate, aacparse->channels);
+ GST_DEBUG ("codec_data: object_type=%d, sample_rate=%d, channels=%d, "
+ "samples=%d", aacparse->object_type, aacparse->sample_rate,
+ aacparse->channels, aacparse->frame_samples);
/* arrange for metadata and get out of the way */
gst_aac_parse_set_src_caps (aacparse, caps);
aacparse->sample_rate = rate;
aacparse->channels = channels;
- if (!gst_aac_parse_set_src_caps (aacparse,
- GST_PAD_CAPS (GST_BASE_PARSE (aacparse)->sinkpad))) {
+ sinkcaps = gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad);
+ if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
/* If linking fails, we need to return appropriate error */
+ gst_caps_unref (sinkcaps);
ret = GST_FLOW_NOT_LINKED;
}
+ gst_caps_unref (sinkcaps);
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
- aacparse->sample_rate, 1024, 2, 2);
+ aacparse->sample_rate, aacparse->frame_samples, 2, 2);
}
return ret;
gst_static_pad_template_get (&src_template));
gst_element_class_set_details_simple (element_class,
- "AC3 audio stream parser", "Codec/Parser/Audio",
+ "AC3 audio stream parser", "Codec/Parser/Converter/Audio",
"AC3 parser", "Tim-Philipp Müller <tim centricular net>");
-}
-
-static void
-gst_ac3_parse_class_init (GstAc3ParseClass * klass)
-{
- GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- GST_DEBUG_CATEGORY_INIT (ac3_parse_debug, "ac3parse", 0,
- "AC3 audio stream parser");
-
- object_class->finalize = gst_ac3_parse_finalize;
parse_class->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
gint skip, guint * frame_size, guint * rate, guint * chans, guint * blks,
guint * sid)
{
- GstBitReader bits = GST_BIT_READER_INIT_FROM_BUFFER (buf);
+ GstBitReader bits;
+ gpointer data;
+ gsize size;
- guint8 fscod, frmsizcod, bsid, acmod, lfe_on;
+ guint8 fscod, frmsizcod, bsid, acmod, lfe_on, rate_scale;
+ gboolean ret = FALSE;
GST_LOG_OBJECT (ac3parse, "parsing ac3");
gst_object_unref (peer_pad);
}
+ static void
+ gst_navseek_toggle_play_pause (GstNavSeek * navseek)
+ {
+ GstStateChangeReturn sret;
+ GstState current, pending, state;
+
+ sret = gst_element_get_state (GST_ELEMENT (navseek), ¤t, &pending, 0);
+ if (sret == GST_STATE_CHANGE_FAILURE)
+ return;
+
+ state = (pending != GST_STATE_VOID_PENDING) ? pending : current;
+
+ gst_element_post_message (GST_ELEMENT (navseek),
+ gst_message_new_request_state (GST_OBJECT (navseek),
+ (state == GST_STATE_PLAYING) ? GST_STATE_PAUSED : GST_STATE_PLAYING));
+ }
+
static gboolean
-gst_navseek_handle_src_event (GstPad * pad, GstEvent * event)
+gst_navseek_src_event (GstBaseTransform * trans, GstEvent * event)
{
GstNavSeek *navseek;
gboolean ret = TRUE;
return ret;
}
+ static void
+ gst_flv_mux_reset_pad (GstFlvMux * mux, GstFlvPad * cpad, gboolean video)
+ {
+ cpad->video = video;
+
+ if (cpad->audio_codec_data)
+ gst_buffer_unref (cpad->audio_codec_data);
+ cpad->audio_codec_data = NULL;
+ cpad->audio_codec = G_MAXUINT;
+ cpad->rate = G_MAXUINT;
+ cpad->width = G_MAXUINT;
+ cpad->channels = G_MAXUINT;
+
+ if (cpad->video_codec_data)
+ gst_buffer_unref (cpad->video_codec_data);
+ cpad->video_codec_data = NULL;
+ cpad->video_codec = G_MAXUINT;
+ cpad->last_timestamp = 0;
+ }
+
static GstPad *
gst_flv_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * pad_name)
+ GstPadTemplate * templ, const gchar * req_name, const GstCaps * caps)
{
GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
GstFlvMux *mux = GST_FLV_MUX (element);
buf = pad->prepare_buf_func (pad, buf, qtmux);
}
- buf = gst_buffer_make_metadata_writable (buf);
+ if (G_LIKELY (buf != NULL && GST_CLOCK_TIME_IS_VALID (pad->first_ts))) {
++ buf = gst_buffer_make_writable (buf);
+ check_and_subtract_ts (qtmux, &GST_BUFFER_TIMESTAMP (buf), pad->first_ts);
+ }
+ /* when we obtain the first_ts we subtract from all stored buffers we have,
+ * after that we can subtract on input */
+
again:
last_buf = pad->last_buf;
- if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER)) {
+ if (qtmux->dts_method == DTS_METHOD_REORDER) {
buf = gst_qt_mux_get_asc_buffer_ts (qtmux, pad, buf);
if (!buf && !last_buf) {
GST_DEBUG_OBJECT (qtmux, "no reordered buffer");
}
}
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = data + 14;
- GST_BUFFER_SIZE (buf) = len - 14;
+ static void
+ qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag,
+ const char *tag_bis, GNode * node)
+ {
+ guint8 *data;
+ GstBuffer *buf;
+ guint len;
+ GstTagList *taglist = NULL;
+
+ GST_LOG_OBJECT (demux, "parsing ID32");
+
+ data = node->data;
+ len = GST_READ_UINT32_BE (data);
+
+ /* need at least full box and language tag */
+ if (len < 12 + 2)
+ return;
+
++ buf = gst_buffer_new_allocate (NULL, len - 14, 0);
++ gst_buffer_fill (buf, 0, data + 14, len - 14);
+
+ taglist = gst_tag_list_from_id3v2_tag (buf);
+ if (taglist) {
+ GST_LOG_OBJECT (demux, "parsing ok");
+ gst_tag_list_insert (demux->tag_list, taglist, GST_TAG_MERGE_KEEP);
+ } else {
+ GST_LOG_OBJECT (demux, "parsing failed");
+ }
+
+ if (taglist)
+ gst_tag_list_free (taglist);
+
+ gst_buffer_unref (buf);
+ }
+
typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
const char *tag, const char *tag_bis, GNode * node);
GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
else
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
--
- gst_base_rtp_depayload_push (depayload, outbuf);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (depayload->srcpad));
}
- return TRUE;
+ return outbuf;
/* ERRORS */
short_nal:
{
GST_WARNING_OBJECT (depayload, "dropping short NAL");
+ gst_buffer_unmap (nal, data, size);
gst_buffer_unref (nal);
- return FALSE;
+ return NULL;
}
}
outdata[2] = (outsize >> 8);
outdata[3] = (outsize);
}
+ gst_buffer_unmap (outbuf, outdata, -1);
- gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf,
- rtph264depay->fu_timestamp, rtph264depay->fu_marker);
-
rtph264depay->current_fu_type = 0;
+
+ if (send) {
+ outbuf = gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf,
+ rtph264depay->fu_timestamp, rtph264depay->fu_marker);
+ if (outbuf)
+ gst_base_rtp_depayload_push (GST_BASE_RTP_DEPAYLOAD (rtph264depay),
+ outbuf);
+ return NULL;
+ } else {
+ return gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf,
+ rtph264depay->fu_timestamp, rtph264depay->fu_marker);
+ }
}
static GstBuffer *
gst_rtp_h264_depay_process (GstBaseRTPDepayload * depayload, GstBuffer * buf)
{
GstRtpH264Depay *rtph264depay;
- GstBuffer *outbuf;
+ GstBuffer *outbuf = NULL;
guint8 nal_unit_type;
+ GstRTPBuffer rtp = { NULL };
rtph264depay = GST_RTP_H264_DEPAY (depayload);
outdata[2] = nalu_size >> 8;
outdata[3] = nalu_size & 0xff;
}
- outdata += sizeof (sync_bytes);
- memcpy (outdata, payload, nalu_size);
+ memcpy (outdata + sizeof (sync_bytes), payload, nalu_size);
+ gst_buffer_unmap (outbuf, outdata, outsize);
- gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp, marker);
+ outbuf = gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp,
+ marker);
break;
}
}
+ gst_rtp_buffer_unmap (&rtp);
}
- return NULL;
+ return outbuf;
/* ERRORS */
undefined_type:
guint64 base_rtptime;
guint64 base_time;
guint clock_rate;
+ guint64 clock_base;
guint64 extrtptime;
GstBuffer *buffer;
+ GstRTCPBuffer rtcp = { NULL };
bin = stream->bin;
guint64 ext_rtptime, diff;
guint32 rtptime;
gboolean drop = FALSE;
+ GstRTCPBuffer rtcp = { NULL };
+ guint64 clock_base;
jitterbuffer = GST_RTP_JITTER_BUFFER (gst_pad_get_parent (pad));
break;
}
- rtptime = gst_rtp_buffer_get_timestamp (buf);
+ rtptime = gst_rtp_buffer_get_timestamp (&rtp);
+ /* rtp time jumps are checked for during skew calculation, but bypassed
+ * in other mode, so mind those here and reset jb if needed.
+ * Only reset if valid input time, which is likely for UDP input
+ * where we expect this might happen due to async thread effects
+ * (in seek and state change cycles), but not so much for TCP input */
+ if (GST_CLOCK_TIME_IS_VALID (time) &&
+ jbuf->mode != RTP_JITTER_BUFFER_MODE_SLAVE &&
+ jbuf->base_time != -1 && jbuf->last_rtptime != -1) {
+ GstClockTime ext_rtptime = jbuf->ext_rtptime;
+
+ ext_rtptime = gst_rtp_buffer_ext_timestamp (&ext_rtptime, rtptime);
+ if (ext_rtptime > jbuf->last_rtptime + 3 * clock_rate ||
+ ext_rtptime + 3 * clock_rate < jbuf->last_rtptime) {
+ /* reset even if we don't have valid incoming time;
+ * still better than producing possibly very bogus output timestamp */
+ GST_WARNING ("rtp delta too big, reset skew");
+ rtp_jitter_buffer_reset_skew (jbuf);
+ }
+ }
+
switch (jbuf->mode) {
case RTP_JITTER_BUFFER_MODE_NONE:
case RTP_JITTER_BUFFER_MODE_BUFFER:
cmd = CMD_WAIT;
state = GST_STATE_PAUSED;
} else {
- event = gst_event_new_flush_stop ();
+ event = gst_event_new_flush_stop (TRUE);
- GST_DEBUG_OBJECT (src, "stop flush");
+ GST_DEBUG_OBJECT (src, "stop flush; playing %d", playing);
cmd = CMD_LOOP;
- state = GST_STATE_PLAYING;
+ if (playing)
+ state = GST_STATE_PLAYING;
+ else
+ state = GST_STATE_PAUSED;
clock = gst_element_get_clock (GST_ELEMENT_CAST (src));
if (clock) {
base_time = gst_clock_get_time (clock);
if (flush) {
/* if we started flush, we stop now */
GST_DEBUG_OBJECT (src, "stopping flush");
- gst_rtspsrc_flush (src, FALSE);
+ gst_rtspsrc_flush (src, FALSE, playing);
- } else if (src->running) {
- /* re-engage loop */
- gst_rtspsrc_loop_send_cmd (src, CMD_LOOP, FALSE);
-
- /* we are running the current segment and doing a non-flushing seek,
- * close the segment first based on the previous last_stop. */
- GST_DEBUG_OBJECT (src, "closing running segment %" G_GINT64_FORMAT
- " to %" G_GINT64_FORMAT, src->segment.accum, src->segment.last_stop);
-
- /* queue the segment for sending in the stream thread */
- if (src->close_segment)
- gst_event_unref (src->close_segment);
- src->close_segment = gst_event_new_new_segment (TRUE,
- src->segment.rate, src->segment.format,
- src->segment.accum, src->segment.last_stop, src->segment.accum);
-
- /* keep track of our last_stop */
- seeksegment.accum = src->segment.last_stop;
}
/* now we did the seek and can activate the new segment values */
PROP_ENDX,
PROP_ENDY,
PROP_REMOTE,
+ PROP_XID,
+ PROP_XNAME,
};
-GST_BOILERPLATE (GstXImageSrc, gst_ximage_src, GstPushSrc, GST_TYPE_PUSH_SRC);
+#define gst_ximage_src_parent_class parent_class
+G_DEFINE_TYPE (GstXImageSrc, gst_ximage_src, GST_TYPE_PUSH_SRC);
static void gst_ximage_src_fixate (GstPad * pad, GstCaps * caps);
static void gst_ximage_src_clear_bufpool (GstXImageSrc * ximagesrc);
g_param_spec_boolean ("remote", "Remote dispay",
"Whether the display is remote", FALSE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
+ /**
+ * GstXImageSrc:xid
+ *
+ * The XID of the window to capture. 0 for the root window (default).
+ *
+ * Since: 0.10.31
+ **/
+ g_object_class_install_property (gc, PROP_XID,
+ g_param_spec_uint64 ("xid", "Window XID",
+ "Window XID to capture from", 0, G_MAXUINT64, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
+ /**
+ * GstXImageSrc:xname
+ *
+ * The name of the window to capture, if any.
+ *
+ * Since: 0.10.31
+ **/
+ g_object_class_install_property (gc, PROP_XNAME,
+ g_param_spec_string ("xname", "Window name",
+ "Window name to capture from", NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- parent_class = g_type_class_peek_parent (klass);
+ gst_element_class_set_details_simple (ec, "Ximage video source",
+ "Source/Video",
+ "Creates a screenshot video stream",
+ "Lutz Mueller <lutz@users.sourceforge.net>, "
+ "Jan Schmidt <thaytan@mad.scientist.com>, "
+ "Zaheer Merali <zaheerabbas at merali dot org>");
+ gst_element_class_add_pad_template (ec, gst_static_pad_template_get (&t));
push_class->create = gst_ximage_src_create;
bc->get_caps = gst_ximage_src_get_caps;