From 62619e9d0343ce810581f29ae68d8c98619fe7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 6 Jul 2009 16:24:59 +0100 Subject: mimenc: Add property for the paused mode --- ext/mimic/gstmimenc.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++ ext/mimic/gstmimenc.h | 2 ++ 2 files changed, 61 insertions(+) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index a69ab2cc..b9d7a987 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -42,6 +42,15 @@ GST_DEBUG_CATEGORY (mimenc_debug); #define MAX_INTERFRAMES 15 + +enum +{ + PROP_0, + PROP_PAUSED_MODE, + PROP_LAST +}; + + static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, @@ -80,6 +89,10 @@ static GstBuffer *gst_mimenc_create_tcp_header (GstMimEnc * mimenc, static GstStateChangeReturn gst_mimenc_change_state (GstElement * element, GstStateChange transition); +static void gst_mimenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_mimenc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); GST_BOILERPLATE (GstMimEnc, gst_mimenc, GstElement, GST_TYPE_ELEMENT); @@ -93,6 +106,16 @@ gst_mimenc_base_init (gpointer klass) "Andre Moreira Magalhaes " }; GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_mimenc_set_property; + gobject_class->get_property = gst_mimenc_get_property; + + g_object_class_install_property (gobject_class, PROP_PAUSED_MODE, + g_param_spec_boolean ("paused-mode", "Paused mode", + "If enabled, empty frames will be generated every 4 seconds" + " when no data is received", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_factory)); @@ -139,6 +162,42 @@ gst_mimenc_init (GstMimEnc * mimenc, GstMimEncClass * klass) mimenc->frames = 0; } +static void +gst_mimenc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMimEnc *mimenc = GST_MIMENC (object); + + switch (prop_id) { + case PROP_PAUSED_MODE: + GST_OBJECT_LOCK (mimenc); + mimenc->paused_mode = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (mimenc); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_mimenc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstMimEnc *mimenc = GST_MIMENC (object); + + switch (prop_id) { + case PROP_PAUSED_MODE: + GST_OBJECT_LOCK (mimenc); + g_value_set_boolean (value, mimenc->paused_mode); + GST_OBJECT_UNLOCK (mimenc); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static gboolean gst_mimenc_setcaps (GstPad * pad, GstCaps * caps) { diff --git a/ext/mimic/gstmimenc.h b/ext/mimic/gstmimenc.h index c21d714f..ca233eb7 100644 --- a/ext/mimic/gstmimenc.h +++ b/ext/mimic/gstmimenc.h @@ -54,6 +54,8 @@ struct _GstMimEnc gint buffer_size; guint32 frames; guint16 height, width; + + gboolean paused_mode; }; struct _GstMimEncClass -- cgit v1.2.1 From 39b8f2486675a4c128a46f3a2bf3848da913345c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 6 Jul 2009 17:17:22 +0100 Subject: mimenc: Save the segment --- ext/mimic/gstmimenc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++ ext/mimic/gstmimenc.h | 1 + 2 files changed, 80 insertions(+) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index b9d7a987..206ff3c9 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -85,6 +85,7 @@ static gboolean gst_mimenc_setcaps (GstPad * pad, GstCaps * caps); static GstFlowReturn gst_mimenc_chain (GstPad * pad, GstBuffer * in); static GstBuffer *gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, guint32 timestamp); +static gboolean gst_mimenc_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn gst_mimenc_change_state (GstElement * element, GstStateChange transition); @@ -146,6 +147,7 @@ gst_mimenc_init (GstMimEnc * mimenc, GstMimEncClass * klass) gst_element_add_pad (GST_ELEMENT (mimenc), mimenc->sinkpad); gst_pad_set_setcaps_function (mimenc->sinkpad, gst_mimenc_setcaps); gst_pad_set_chain_function (mimenc->sinkpad, gst_mimenc_chain); + gst_pad_set_event_function (mimenc->sinkpad, gst_mimenc_event); mimenc->srcpad = gst_pad_new_from_template (gst_static_pad_template_get (&src_factory), @@ -154,6 +156,8 @@ gst_mimenc_init (GstMimEnc * mimenc, GstMimEncClass * klass) mimenc->enc = NULL; + gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); + // TODO property to set resolution mimenc->res = MIMIC_RES_HIGH; mimenc->buffer_size = -1; @@ -263,6 +267,14 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) GST_OBJECT_LOCK (mimenc); + if (mimenc->segment.format == GST_FORMAT_UNDEFINED) { + GST_WARNING_OBJECT (mimenc, "No new-segment received," + " initializing segment with time 0..-1"); + gst_segment_init (&mimenc->segment, GST_FORMAT_TIME); + gst_segment_set_newsegment (&mimenc->segment, + FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + } + if (mimenc->enc == NULL) { mimenc->enc = mimic_open (); if (mimenc->enc == NULL) { @@ -363,6 +375,68 @@ gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, return buf_header; } +static gboolean +gst_mimenc_event (GstPad * pad, GstEvent * event) +{ + GstMimEnc *mimenc = GST_MIMENC (gst_pad_get_parent (pad)); + gboolean ret = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + gboolean update; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, + &format, &start, &stop, &time); + + /* we need time for now */ + if (format != GST_FORMAT_TIME) + goto newseg_wrong_format; + + GST_DEBUG_OBJECT (mimenc, + "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, + update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (time)); + + /* now configure the values, we need these to time the release of the + * buffers on the srcpad. */ + GST_OBJECT_LOCK (mimenc); + gst_segment_set_newsegment_full (&mimenc->segment, update, + rate, arate, format, start, stop, time); + GST_OBJECT_UNLOCK (mimenc); + break; + + } + break; + case GST_EVENT_FLUSH_STOP: + GST_OBJECT_LOCK (mimenc); + gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); + GST_OBJECT_UNLOCK (mimenc); + break; + default: + break; + } + + ret = gst_pad_push_event (mimenc->srcpad, event); + +done: + gst_object_unref (mimenc); + + return ret; + +newseg_wrong_format: + { + GST_DEBUG_OBJECT (mimenc, "received non TIME newsegment"); + gst_event_unref (event); + ret = FALSE; + goto done; + } +} + static GstStateChangeReturn gst_mimenc_change_state (GstElement * element, GstStateChange transition) { @@ -381,6 +455,11 @@ gst_mimenc_change_state (GstElement * element, GstStateChange transition) GST_OBJECT_UNLOCK (element); break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_OBJECT_LOCK (mimenc); + gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); + GST_OBJECT_UNLOCK (mimenc); + break; default: break; } diff --git a/ext/mimic/gstmimenc.h b/ext/mimic/gstmimenc.h index ca233eb7..7b1daa56 100644 --- a/ext/mimic/gstmimenc.h +++ b/ext/mimic/gstmimenc.h @@ -56,6 +56,7 @@ struct _GstMimEnc guint16 height, width; gboolean paused_mode; + GstSegment segment; }; struct _GstMimEncClass -- cgit v1.2.1 From a97e0f0a941e6999a8371e5dc2ebbeddb0bdb309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 7 Jul 2009 18:22:54 +0100 Subject: mimenc: Retimestamp to the running time --- ext/mimic/gstmimenc.c | 50 +++++++++++++++++++++++++++++++++++++++----------- ext/mimic/gstmimenc.h | 2 ++ 2 files changed, 41 insertions(+), 11 deletions(-) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index 206ff3c9..c3d3688c 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -259,6 +259,7 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) gint buffer_size; GstBuffer *header = NULL; GstFlowReturn res = GST_FLOW_OK; + GstEvent *event = NULL; g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); mimenc = GST_MIMENC (gst_pad_get_parent (pad)); @@ -304,7 +305,10 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) data = GST_BUFFER_DATA (buf); out_buf = gst_buffer_new_and_alloc (mimenc->buffer_size); - GST_BUFFER_TIMESTAMP (out_buf) = GST_BUFFER_TIMESTAMP (buf); + GST_BUFFER_TIMESTAMP (out_buf) = + gst_segment_to_running_time (&mimenc->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf)); + mimenc->last_buffer = GST_BUFFER_TIMESTAMP (out_buf); buffer_size = mimenc->buffer_size; if (!mimic_encode_frame (mimenc->enc, data, GST_BUFFER_DATA (out_buf), &buffer_size, @@ -325,21 +329,38 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) header = gst_mimenc_create_tcp_header (mimenc, buffer_size, GST_BUFFER_TIMESTAMP (buf) / GST_MSECOND); + if (!header) { + gst_buffer_unref (out_buf); + GST_DEBUG_OBJECT (mimenc, "header not created succesfully"); + res = GST_FLOW_ERROR; + goto out_unlock; + } + + if (mimenc->need_newsegment) { + event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + mimenc->need_newsegment = FALSE; + } + GST_OBJECT_UNLOCK (mimenc); - if (header) { - res = gst_pad_push (mimenc->srcpad, header); - if (res != GST_FLOW_OK) { + if (event) { + if (!gst_pad_push_event (mimenc->srcpad, event)) { + res = GST_FLOW_ERROR; + GST_ERROR_OBJECT (mimenc, "Failed to push NEWSEGMENT event"); + gst_buffer_unref (header); gst_buffer_unref (out_buf); goto out; } + } - res = gst_pad_push (mimenc->srcpad, out_buf); - } else { - GST_DEBUG_OBJECT (mimenc, "header not created succesfully"); - res = GST_FLOW_ERROR; + res = gst_pad_push (mimenc->srcpad, header); + if (res != GST_FLOW_OK) { + gst_buffer_unref (out_buf); + goto out; } + res = gst_pad_push (mimenc->srcpad, out_buf); + out: if (buf) gst_buffer_unref (buf); @@ -380,6 +401,8 @@ gst_mimenc_event (GstPad * pad, GstEvent * event) { GstMimEnc *mimenc = GST_MIMENC (gst_pad_get_parent (pad)); gboolean ret = TRUE; + gboolean forward = TRUE; + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: @@ -408,6 +431,7 @@ gst_mimenc_event (GstPad * pad, GstEvent * event) gst_segment_set_newsegment_full (&mimenc->segment, update, rate, arate, format, start, stop, time); GST_OBJECT_UNLOCK (mimenc); + forward = FALSE; break; } @@ -415,13 +439,17 @@ gst_mimenc_event (GstPad * pad, GstEvent * event) case GST_EVENT_FLUSH_STOP: GST_OBJECT_LOCK (mimenc); gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); + mimenc->need_newsegment = TRUE; GST_OBJECT_UNLOCK (mimenc); break; default: break; } - ret = gst_pad_push_event (mimenc->srcpad, event); + if (forward) + ret = gst_pad_push_event (mimenc->srcpad, event); + else + gst_event_unref (event); done: gst_object_unref (mimenc); @@ -440,11 +468,10 @@ newseg_wrong_format: static GstStateChangeReturn gst_mimenc_change_state (GstElement * element, GstStateChange transition) { - GstMimEnc *mimenc; + GstMimEnc *mimenc = GST_MIMENC (element);; switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: - mimenc = GST_MIMENC (element); GST_OBJECT_LOCK (element); if (mimenc->enc != NULL) { mimic_close (mimenc->enc); @@ -458,6 +485,7 @@ gst_mimenc_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: GST_OBJECT_LOCK (mimenc); gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); + mimenc->last_buffer = GST_CLOCK_TIME_NONE; GST_OBJECT_UNLOCK (mimenc); break; default: diff --git a/ext/mimic/gstmimenc.h b/ext/mimic/gstmimenc.h index 7b1daa56..27b0a1d8 100644 --- a/ext/mimic/gstmimenc.h +++ b/ext/mimic/gstmimenc.h @@ -57,6 +57,8 @@ struct _GstMimEnc gboolean paused_mode; GstSegment segment; + gboolean need_newsegment; + GstClockTime last_buffer; }; struct _GstMimEncClass -- cgit v1.2.1 From 4bf9fe969e154ee5f20a8f3946589a642ab746c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 7 Jul 2009 18:18:06 +0100 Subject: mimenc: Put timestamp on the header buffer --- ext/mimic/gstmimenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index c3d3688c..9f6727f5 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -84,7 +84,7 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", static gboolean gst_mimenc_setcaps (GstPad * pad, GstCaps * caps); static GstFlowReturn gst_mimenc_chain (GstPad * pad, GstBuffer * in); static GstBuffer *gst_mimenc_create_tcp_header (GstMimEnc * mimenc, - guint32 payload_size, guint32 timestamp); + guint32 payload_size, GstClockTime timestamp); static gboolean gst_mimenc_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn @@ -327,7 +327,7 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) // now let's create that tcp header header = gst_mimenc_create_tcp_header (mimenc, buffer_size, - GST_BUFFER_TIMESTAMP (buf) / GST_MSECOND); + GST_BUFFER_TIMESTAMP (out_buf)); if (!header) { gst_buffer_unref (out_buf); @@ -376,12 +376,14 @@ out_unlock: static GstBuffer * gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, - guint32 timestamp) + GstClockTime timestamp) { // 24 bytes GstBuffer *buf_header = gst_buffer_new_and_alloc (24); guchar *p = (guchar *) GST_BUFFER_DATA (buf_header); + GST_BUFFER_TIMESTAMP (buf_header) = timestamp; + p[0] = 24; *((guchar *) (p + 1)) = 0; *((guint16 *) (p + 2)) = GUINT16_TO_LE (mimenc->width); @@ -391,7 +393,7 @@ gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, *((guint32 *) (p + 12)) = GUINT32_TO_LE (GST_MAKE_FOURCC ('M', 'L', '2', '0')); *((guint32 *) (p + 16)) = 0; - *((guint32 *) (p + 20)) = timestamp; + *((guint32 *) (p + 20)) = timestamp / GST_MSECOND; return buf_header; } -- cgit v1.2.1 From 316236761c6fd3063471e9cab267a11d0466dfa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 7 Jul 2009 18:27:36 +0100 Subject: mimenc: Put keyframe/paused flags in tcp header --- ext/mimic/gstmimenc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index 9f6727f5..ab2f4a01 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -84,7 +84,8 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", static gboolean gst_mimenc_setcaps (GstPad * pad, GstCaps * caps); static GstFlowReturn gst_mimenc_chain (GstPad * pad, GstBuffer * in); static GstBuffer *gst_mimenc_create_tcp_header (GstMimEnc * mimenc, - guint32 payload_size, GstClockTime timestamp); + guint32 payload_size, GstClockTime timestamp, gboolean keyframe, + gboolean paused); static gboolean gst_mimenc_event (GstPad * pad, GstEvent * event); static GstStateChangeReturn @@ -260,6 +261,7 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) GstBuffer *header = NULL; GstFlowReturn res = GST_FLOW_OK; GstEvent *event = NULL; + gboolean keyframe; g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR); mimenc = GST_MIMENC (gst_pad_get_parent (pad)); @@ -310,9 +312,9 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) GST_BUFFER_TIMESTAMP (buf)); mimenc->last_buffer = GST_BUFFER_TIMESTAMP (out_buf); buffer_size = mimenc->buffer_size; + keyframe = (mimenc->frames % MAX_INTERFRAMES) == 0 ? TRUE : FALSE; if (!mimic_encode_frame (mimenc->enc, data, GST_BUFFER_DATA (out_buf), - &buffer_size, - ((mimenc->frames % MAX_INTERFRAMES) == 0 ? TRUE : FALSE))) { + &buffer_size, keyframe)) { GST_WARNING_OBJECT (mimenc, "mimic_encode_frame error\n"); gst_buffer_unref (out_buf); gst_buffer_unref (buf); @@ -327,7 +329,7 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in) // now let's create that tcp header header = gst_mimenc_create_tcp_header (mimenc, buffer_size, - GST_BUFFER_TIMESTAMP (out_buf)); + GST_BUFFER_TIMESTAMP (out_buf), keyframe, FALSE); if (!header) { gst_buffer_unref (out_buf); @@ -376,7 +378,7 @@ out_unlock: static GstBuffer * gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, - GstClockTime timestamp) + GstClockTime timestamp, gboolean keyframe, gboolean paused) { // 24 bytes GstBuffer *buf_header = gst_buffer_new_and_alloc (24); @@ -385,10 +387,10 @@ gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size, GST_BUFFER_TIMESTAMP (buf_header) = timestamp; p[0] = 24; - *((guchar *) (p + 1)) = 0; + *((guchar *) (p + 1)) = paused ? 1 : 0; *((guint16 *) (p + 2)) = GUINT16_TO_LE (mimenc->width); *((guint16 *) (p + 4)) = GUINT16_TO_LE (mimenc->height); - *((guint16 *) (p + 6)) = 0; + *((guint16 *) (p + 6)) = keyframe ? 1 : 0; *((guint32 *) (p + 8)) = GUINT32_TO_LE (payload_size); *((guint32 *) (p + 12)) = GUINT32_TO_LE (GST_MAKE_FOURCC ('M', 'L', '2', '0')); -- cgit v1.2.1 From f410614403c56dbfc833119d7ad6f0c38f1fabd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 7 Jul 2009 19:15:42 +0100 Subject: mimdec: Ignore pause frames --- ext/mimic/gstmimdec.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'ext') diff --git a/ext/mimic/gstmimdec.c b/ext/mimic/gstmimdec.c index c7f1ec87..1579bd41 100644 --- a/ext/mimic/gstmimdec.c +++ b/ext/mimic/gstmimdec.c @@ -172,7 +172,7 @@ gst_mimdec_chain (GstPad * pad, GstBuffer * in) (mimdec->have_header ? mimdec->payload_size : 24)) { if (!mimdec->have_header) { header = (guchar *) gst_adapter_peek (mimdec->adapter, 24); - header_size = GUINT16_FROM_LE (*(guint16 *) (header + 0)); + header_size = header[0]; if (header_size != 24) { GST_WARNING_OBJECT (mimdec, "invalid frame: header size %d incorrect", header_size); @@ -201,6 +201,12 @@ gst_mimdec_chain (GstPad * pad, GstBuffer * in) mimdec->have_header = TRUE; } + /* Check if its paused frame, drop it */ + if (mimdec->payload_size == 0) { + mimdec->have_header = FALSE; + continue; + } + if (gst_adapter_available (mimdec->adapter) < mimdec->payload_size) { goto out; } -- cgit v1.2.1 From 89e30492966c8f24552d204814a1f30f39bde60c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 7 Jul 2009 19:18:16 +0100 Subject: mimenc: Send pause frames when paused --- ext/mimic/gstmimenc.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++- ext/mimic/gstmimenc.h | 2 + 2 files changed, 123 insertions(+), 2 deletions(-) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index ab2f4a01..66c74230 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -469,10 +469,96 @@ newseg_wrong_format: } } +static void +paused_mode_task (gpointer data) +{ + GstMimEnc *mimenc = GST_MIMENC (data); + GstClockTime now; + GstClockTimeDiff diff; + GstFlowReturn ret; + + if (!GST_ELEMENT_CLOCK (mimenc)) { + GST_ERROR_OBJECT (mimenc, "Element has no clock"); + gst_pad_pause_task (mimenc->srcpad); + return; + } + + GST_OBJECT_LOCK (mimenc); + + if (mimenc->stop_paused_mode) { + GST_OBJECT_UNLOCK (mimenc); + goto stop_task; + } + + now = gst_clock_get_time (GST_ELEMENT_CLOCK (mimenc)); + + diff = now - GST_ELEMENT_CAST (mimenc)->base_time - mimenc->last_buffer; + if (diff < 0) + diff = 0; + + if (diff > 3.95 * GST_SECOND) { + GstBuffer *buffer = gst_mimenc_create_tcp_header (mimenc, 0, + mimenc->last_buffer + 4 * GST_SECOND, FALSE, TRUE); + GstEvent *event = NULL; + + mimenc->last_buffer += 4 * GST_SECOND; + + if (mimenc->need_newsegment) { + event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + mimenc->need_newsegment = FALSE; + } + + GST_OBJECT_UNLOCK (mimenc); + GST_LOG_OBJECT (mimenc, "Haven't had an incoming buffer in 4 seconds," + " sending out a pause frame"); + + if (event) { + if (!gst_pad_push_event (mimenc->srcpad, event)) { + GST_ERROR_OBJECT (mimenc, "Failed to push NEWSEGMENT event"); + gst_buffer_unref (buffer); + goto stop_task; + } + } + ret = gst_pad_push (mimenc->srcpad, buffer); + if (ret < 0) { + GST_WARNING_OBJECT (mimenc, "Error pushing paused header: %s", + gst_flow_get_name (ret)); + goto stop_task; + } + } else { + GstClockTime next_stop; + GstClockID id; + + next_stop = now + (4 * GST_SECOND - MIN (diff, 4 * GST_SECOND)); + + id = gst_clock_new_single_shot_id (GST_ELEMENT_CLOCK (mimenc), next_stop); + + if (mimenc->stop_paused_mode) { + GST_OBJECT_UNLOCK (mimenc); + goto stop_task; + } + + mimenc->clock_id = id; + GST_OBJECT_UNLOCK (mimenc); + + gst_clock_id_wait (id, NULL); + + GST_OBJECT_LOCK (mimenc); + mimenc->clock_id = NULL; + GST_OBJECT_UNLOCK (mimenc); + } + return; + +stop_task: + + gst_pad_pause_task (mimenc->srcpad); +} + static GstStateChangeReturn gst_mimenc_change_state (GstElement * element, GstStateChange transition) { - GstMimEnc *mimenc = GST_MIMENC (element);; + GstMimEnc *mimenc = GST_MIMENC (element); + GstStateChangeReturn ret; switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: @@ -490,11 +576,44 @@ gst_mimenc_change_state (GstElement * element, GstStateChange transition) GST_OBJECT_LOCK (mimenc); gst_segment_init (&mimenc->segment, GST_FORMAT_UNDEFINED); mimenc->last_buffer = GST_CLOCK_TIME_NONE; + mimenc->need_newsegment = TRUE; + GST_OBJECT_UNLOCK (mimenc); + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_OBJECT_LOCK (mimenc); + if (mimenc->clock_id) + gst_clock_id_unschedule (mimenc->clock_id); + mimenc->stop_paused_mode = TRUE; + GST_OBJECT_UNLOCK (mimenc); + + gst_pad_pause_task (mimenc->srcpad); + + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_OBJECT_LOCK (mimenc); + mimenc->stop_paused_mode = FALSE; + if (mimenc->last_buffer == GST_CLOCK_TIME_NONE) + mimenc->last_buffer = gst_clock_get_time (GST_ELEMENT_CLOCK (mimenc)) + - GST_ELEMENT_CAST (mimenc)->base_time; GST_OBJECT_UNLOCK (mimenc); + if (!gst_pad_start_task (mimenc->srcpad, paused_mode_task, mimenc)) { + ret = GST_STATE_CHANGE_FAILURE; + GST_ERROR_OBJECT (mimenc, "Can not start task"); + } break; default: break; } - return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + return ret; } diff --git a/ext/mimic/gstmimenc.h b/ext/mimic/gstmimenc.h index 27b0a1d8..89cff46e 100644 --- a/ext/mimic/gstmimenc.h +++ b/ext/mimic/gstmimenc.h @@ -59,6 +59,8 @@ struct _GstMimEnc GstSegment segment; gboolean need_newsegment; GstClockTime last_buffer; + GstClockID clock_id; + gboolean stop_paused_mode; }; struct _GstMimEncClass -- cgit v1.2.1 From 011e9c10f0e01e347a5becb2ba1bcd50cbad167b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 10 Jul 2009 13:03:54 +0100 Subject: ivorbis: extract vorbis comments Fixes #575818. --- ext/ivorbis/Makefile.am | 4 ++-- ext/ivorbis/vorbisdec.c | 19 +++++++++++-------- 2 files changed, 13 insertions(+), 10 deletions(-) (limited to 'ext') diff --git a/ext/ivorbis/Makefile.am b/ext/ivorbis/Makefile.am index 9fbea14c..83db5eab 100644 --- a/ext/ivorbis/Makefile.am +++ b/ext/ivorbis/Makefile.am @@ -3,10 +3,10 @@ plugin_LTLIBRARIES = libgstivorbis.la libgstivorbis_la_SOURCES = vorbis.c vorbisfile.c vorbisdec.c libgstivorbis_la_CFLAGS = $(GST_CFLAGS) $(IVORBIS_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) libgstivorbis_la_LIBADD = $(IVORBIS_LIBS) \ - $(IVORBISFILE_LIBS) \ $(GST_BASE_LIBS) \ $(GST_PLUGINS_BASE_LIBS) \ - -lgstaudio-@GST_MAJORMINOR@ + -lgstaudio-@GST_MAJORMINOR@ \ + -lgsttag-@GST_MAJORMINOR@ libgstivorbis_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstivorbis_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/ivorbis/vorbisdec.c b/ext/ivorbis/vorbisdec.c index 325c46a3..4502a773 100644 --- a/ext/ivorbis/vorbisdec.c +++ b/ext/ivorbis/vorbisdec.c @@ -651,23 +651,26 @@ channel_count_error: static GstFlowReturn vorbis_handle_comment_packet (GstIVorbisDec * vd, ogg_packet * packet) { -#if 0 guint bitrate = 0; gchar *encoder = NULL; - GstTagList *list; + GstTagList *list, *old_list; GstBuffer *buf; GST_DEBUG_OBJECT (vd, "parsing comment packet"); - buf = gst_buffer_new_and_alloc (packet->bytes); - GST_BUFFER_DATA (buf) = packet->packet; + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = packet->packet->buffer->data; + GST_BUFFER_SIZE (buf) = packet->packet->buffer->size; list = gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7, &encoder); + old_list = vd->taglist; vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE); + if (old_list) + gst_tag_list_free (old_list); gst_tag_list_free (list); gst_buffer_unref (buf); @@ -683,18 +686,18 @@ vorbis_handle_comment_packet (GstIVorbisDec * vd, ogg_packet * packet) gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER_VERSION, vd->vi.version, GST_TAG_AUDIO_CODEC, "Vorbis", NULL); - if (vd->vi.bitrate_nominal > 0) { + if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL); bitrate = vd->vi.bitrate_nominal; } - if (vd->vi.bitrate_upper > 0) { + if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL); if (!bitrate) bitrate = vd->vi.bitrate_upper; } - if (vd->vi.bitrate_lower > 0) { + if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) { gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL); if (!bitrate) @@ -715,7 +718,7 @@ vorbis_handle_comment_packet (GstIVorbisDec * vd, ogg_packet * packet) gst_element_post_message (GST_ELEMENT_CAST (vd), gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist))); } -#endif + return GST_FLOW_OK; } -- cgit v1.2.1 From d607daaf183eb3e068ec53bbf373ea3a63991aa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Fri, 10 Jul 2009 21:42:19 +0100 Subject: mimenc: Only enable paused mode if the property is true --- ext/mimic/gstmimenc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'ext') diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c index 66c74230..84f34012 100644 --- a/ext/mimic/gstmimenc.c +++ b/ext/mimic/gstmimenc.c @@ -559,6 +559,7 @@ gst_mimenc_change_state (GstElement * element, GstStateChange transition) { GstMimEnc *mimenc = GST_MIMENC (element); GstStateChangeReturn ret; + gboolean paused_mode; switch (transition) { case GST_STATE_CHANGE_READY_TO_NULL: @@ -605,10 +606,13 @@ gst_mimenc_change_state (GstElement * element, GstStateChange transition) if (mimenc->last_buffer == GST_CLOCK_TIME_NONE) mimenc->last_buffer = gst_clock_get_time (GST_ELEMENT_CLOCK (mimenc)) - GST_ELEMENT_CAST (mimenc)->base_time; + paused_mode = mimenc->paused_mode; GST_OBJECT_UNLOCK (mimenc); - if (!gst_pad_start_task (mimenc->srcpad, paused_mode_task, mimenc)) { - ret = GST_STATE_CHANGE_FAILURE; - GST_ERROR_OBJECT (mimenc, "Can not start task"); + if (paused_mode) { + if (!gst_pad_start_task (mimenc->srcpad, paused_mode_task, mimenc)) { + ret = GST_STATE_CHANGE_FAILURE; + GST_ERROR_OBJECT (mimenc, "Can not start task"); + } } break; default: -- cgit v1.2.1