summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ext/ivorbis/Makefile.am4
-rw-r--r--ext/ivorbis/vorbisdec.c19
-rw-r--r--ext/mimic/gstmimdec.c8
-rw-r--r--ext/mimic/gstmimenc.c331
-rw-r--r--ext/mimic/gstmimenc.h7
-rw-r--r--gst-libs/gst/video/Makefile.am2
-rw-r--r--gst/mpegdemux/gstmpegdesc.h17
-rw-r--r--gst/mpegdemux/mpegtspacketizer.c41
-rw-r--r--gst/shapewipe/gstshapewipe.c45
9 files changed, 422 insertions, 52 deletions
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;
}
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;
}
diff --git a/ext/mimic/gstmimenc.c b/ext/mimic/gstmimenc.c
index a69ab2cc..84f34012 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,
@@ -75,11 +84,17 @@ 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, gboolean keyframe,
+ gboolean paused);
+static gboolean gst_mimenc_event (GstPad * pad, GstEvent * event);
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 +108,16 @@ gst_mimenc_base_init (gpointer klass)
"Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>"
};
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));
@@ -123,6 +148,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),
@@ -131,6 +157,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;
@@ -139,6 +167,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)
{
@@ -196,6 +260,8 @@ gst_mimenc_chain (GstPad * pad, GstBuffer * in)
gint buffer_size;
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));
@@ -204,6 +270,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) {
@@ -233,11 +307,14 @@ 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;
+ 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);
@@ -252,23 +329,40 @@ 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), keyframe, FALSE);
+
+ 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);
@@ -284,34 +378,191 @@ out_unlock:
static GstBuffer *
gst_mimenc_create_tcp_header (GstMimEnc * mimenc, guint32 payload_size,
- guint32 timestamp)
+ GstClockTime timestamp, gboolean keyframe, gboolean paused)
{
// 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;
+ *((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'));
*((guint32 *) (p + 16)) = 0;
- *((guint32 *) (p + 20)) = timestamp;
+ *((guint32 *) (p + 20)) = timestamp / GST_MSECOND;
return buf_header;
}
+static gboolean
+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:
+ {
+ 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);
+ forward = FALSE;
+ break;
+
+ }
+ break;
+ 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;
+ }
+
+ if (forward)
+ ret = gst_pad_push_event (mimenc->srcpad, event);
+ else
+ gst_event_unref (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 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;
+ GstMimEnc *mimenc = GST_MIMENC (element);
+ GstStateChangeReturn ret;
+ gboolean paused_mode;
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);
@@ -322,9 +573,51 @@ 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);
+ 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;
}
- return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ 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;
+ paused_mode = mimenc->paused_mode;
+ GST_OBJECT_UNLOCK (mimenc);
+ 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:
+ break;
+ }
+
+ return ret;
}
diff --git a/ext/mimic/gstmimenc.h b/ext/mimic/gstmimenc.h
index c21d714f..89cff46e 100644
--- a/ext/mimic/gstmimenc.h
+++ b/ext/mimic/gstmimenc.h
@@ -54,6 +54,13 @@ struct _GstMimEnc
gint buffer_size;
guint32 frames;
guint16 height, width;
+
+ gboolean paused_mode;
+ GstSegment segment;
+ gboolean need_newsegment;
+ GstClockTime last_buffer;
+ GstClockID clock_id;
+ gboolean stop_paused_mode;
};
struct _GstMimEncClass
diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am
index 6836a058..ab85d00f 100644
--- a/gst-libs/gst/video/Makefile.am
+++ b/gst-libs/gst/video/Makefile.am
@@ -19,6 +19,6 @@ libgstbasevideo_@GST_MAJORMINOR@include_HEADERS = \
gstbasevideoparse.h
libgstbasevideo_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -DGST_USE_UNSTABLE_API
-libgstbasevideo_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS)
+libgstbasevideo_@GST_MAJORMINOR@_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) -lgstvideo-@GST_MAJORMINOR@
libgstbasevideo_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
diff --git a/gst/mpegdemux/gstmpegdesc.h b/gst/mpegdemux/gstmpegdesc.h
index 84b40009..71b74aa2 100644
--- a/gst/mpegdemux/gstmpegdesc.h
+++ b/gst/mpegdemux/gstmpegdesc.h
@@ -78,6 +78,7 @@
#define DESC_DIRAC_TC_PRIVATE 0xAC
/* DVB tags */
+#define DESC_DVB_CAROUSEL_IDENTIFIER 0x13
#define DESC_DVB_NETWORK_NAME 0x40
#define DESC_DVB_SERVICE_LIST 0x41
#define DESC_DVB_STUFFING 0x42
@@ -302,6 +303,22 @@
#define DESC_DVB_CABLE_DELIVERY_SYSTEM_symbol_rate(desc) (desc + 9)
#define DESC_DVB_CABLE_DELIVERY_SYSTEM_fec_inner(desc) (desc[12] & 0x0F)
+/* DVB Data Broadcast Descriptor */
+#define DESC_DVB_DATA_BROADCAST_data_broadcast_id(desc) (GST_READ_UINT16_BE((desc) + 2))
+#define DESC_DVB_DATA_BROADCAST_component_tag(desc) (desc[4])
+#define DESC_DVB_DATA_BROADCAST_selector_length(desc) (desc[5])
+#define DESC_DVB_DATA_BROADCAST_selector(desc) (desc + 6)
+#define DESC_DVB_DATA_BROADCAST_iso639_language_code(desc) (desc + 6 + DESC_DVB_DATA_BROADCAST_selector_length(desc))
+#define DESC_DVB_DATA_BROADCAST_text_length(desc) (desc + 9 + DESC_DVB_DATA_BROADCAST_selector_length(desc))
+#define DESC_DVB_DATA_BROADCAST_text(desc) (desc + 10 + DESC_DVB_DATA_BROADCAST_selector_length(desc))
+
+/* DVB Data Broadcast Id Descriptor */
+#define DESC_DVB_DATA_BROADCAST_ID_data_broadcast_id(desc) (GST_READ_UINT16_BE((desc) + 2))
+#define DESC_DVB_DATA_BROADCAST_ID_id_selector_byte(desc) (desc + 4)
+
+/* DVB Carousel Identifier Descriptor */
+#define DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id(desc) (GST_READ_UINT32_BE((desc) + 2))
+
typedef struct {
guint n_desc;
guint8 data_length;
diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c
index c9fc325f..5ed71f0c 100644
--- a/gst/mpegdemux/mpegtspacketizer.c
+++ b/gst/mpegdemux/mpegtspacketizer.c
@@ -507,10 +507,48 @@ mpegts_packetizer_parse_pmt (MpegTSPacketizer * packetizer,
GstMPEGDescriptor *desc =
gst_mpeg_descriptor_parse (data, stream_info_length);
if (desc != NULL) {
+ guint8 *desc_data;
if (gst_mpeg_descriptor_find (desc, DESC_DVB_AC3)) {
gst_structure_set (stream_info, "has-ac3", G_TYPE_BOOLEAN, TRUE,
NULL);
}
+ desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_DATA_BROADCAST_ID);
+ if (desc_data) {
+ guint16 data_broadcast_id;
+ data_broadcast_id =
+ DESC_DVB_DATA_BROADCAST_ID_data_broadcast_id (desc_data);
+ gst_structure_set (stream_info, "data-broadcast-id", G_TYPE_UINT,
+ data_broadcast_id, NULL);
+ }
+ desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_DATA_BROADCAST);
+ if (desc_data) {
+ GstStructure *databroadcast_info;
+ guint16 data_broadcast_id;
+ guint8 component_tag;
+ data_broadcast_id =
+ DESC_DVB_DATA_BROADCAST_data_broadcast_id (desc_data);
+ component_tag = DESC_DVB_DATA_BROADCAST_component_tag (desc_data);
+ databroadcast_info = gst_structure_new ("data-broadcast", "id",
+ G_TYPE_UINT, data_broadcast_id, "component-tag", component_tag,
+ NULL);
+ gst_structure_set (stream_info, "data-broadcast", GST_TYPE_STRUCTURE,
+ databroadcast_info, NULL);
+ }
+ desc_data =
+ gst_mpeg_descriptor_find (desc, DESC_DVB_CAROUSEL_IDENTIFIER);
+ if (desc_data) {
+ guint32 carousel_id;
+ carousel_id = DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id (desc_data);
+ gst_structure_set (stream_info, "carousel-id", G_TYPE_UINT,
+ carousel_id, NULL);
+ }
+ desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_STREAM_IDENTIFIER);
+ if (desc_data) {
+ guint8 component_tag;
+ component_tag = DESC_DVB_STREAM_IDENTIFIER_component_tag (desc_data);
+ gst_structure_set (stream_info, "component-tag", G_TYPE_UINT,
+ component_tag, NULL);
+ }
gst_mpeg_descriptor_free (desc);
}
@@ -1874,9 +1912,6 @@ mpegts_packetizer_remove_stream (MpegTSPacketizer * packetizer, gint16 pid)
GST_INFO ("Removing stream for PID %d", pid);
g_hash_table_remove (packetizer->streams, GINT_TO_POINTER ((gint) pid));
-
- g_object_unref (stream->section_adapter);
- g_free (stream);
}
}
diff --git a/gst/shapewipe/gstshapewipe.c b/gst/shapewipe/gstshapewipe.c
index 655cfc50..6b209d0d 100644
--- a/gst/shapewipe/gstshapewipe.c
+++ b/gst/shapewipe/gstshapewipe.c
@@ -96,7 +96,8 @@ static GstStaticPadTemplate video_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("video_sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB));
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB " ; "
+ GST_VIDEO_CAPS_BGRA));
static GstStaticPadTemplate mask_sink_pad_template =
GST_STATIC_PAD_TEMPLATE ("mask_sink",
@@ -113,7 +114,8 @@ static GstStaticPadTemplate mask_sink_pad_template =
static GstStaticPadTemplate src_pad_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
- GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB));
+ GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") " ; " GST_VIDEO_CAPS_ARGB " ; "
+ GST_VIDEO_CAPS_BGRA));
GST_DEBUG_CATEGORY_STATIC (gst_shape_wipe_debug);
#define GST_CAT_DEFAULT gst_shape_wipe_debug
@@ -808,9 +810,9 @@ gst_shape_wipe_blend_ayuv_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
CREATE_AYUV_FUNCTIONS (16, 65536.0f);
CREATE_AYUV_FUNCTIONS (8, 256.0f);
-#define CREATE_ARGB_FUNCTIONS(depth, scale) \
+#define CREATE_ARGB_FUNCTIONS(depth, name, scale, a, r, g, b) \
static GstFlowReturn \
-gst_shape_wipe_blend_argb_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
+gst_shape_wipe_blend_##name##_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
GstBuffer * maskbuf, GstBuffer * outbuf) \
{ \
const guint##depth *mask = (const guint##depth *) GST_BUFFER_DATA (maskbuf); \
@@ -838,22 +840,22 @@ gst_shape_wipe_blend_argb_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
gfloat in = *mask / scale; \
\
if (in < low) { \
- output[0] = 0x00; /* A */ \
- output[1] = 0x00; /* R */ \
- output[2] = 0x00; /* G */ \
- output[3] = 0x00; /* B */ \
+ output[a] = 0x00; /* A */ \
+ output[r] = 0x00; /* R */ \
+ output[g] = 0x00; /* G */ \
+ output[b] = 0x00; /* B */ \
} else if (in >= high) { \
- output[0] = 0xff; /* A */ \
- output[1] = input[1]; /* R */ \
- output[2] = input[2]; /* G */ \
- output[3] = input[3]; /* B */ \
+ output[a] = 0xff; /* A */ \
+ output[r] = input[r]; /* R */ \
+ output[g] = input[g]; /* G */ \
+ output[b] = input[b]; /* B */ \
} else { \
gfloat val = 255.0f * ((in - low) / (high - low)); \
\
- output[0] = CLAMP (val, 0, 255); /* A */ \
- output[1] = input[1]; /* R */ \
- output[2] = input[2]; /* G */ \
- output[3] = input[3]; /* B */ \
+ output[a] = CLAMP (val, 0, 255); /* A */ \
+ output[r] = input[r]; /* R */ \
+ output[g] = input[g]; /* G */ \
+ output[b] = input[b]; /* B */ \
} \
\
mask++; \
@@ -866,8 +868,11 @@ gst_shape_wipe_blend_argb_##depth (GstShapeWipe * self, GstBuffer * inbuf, \
return GST_FLOW_OK; \
}
-CREATE_ARGB_FUNCTIONS (16, 65536.0f);
-CREATE_ARGB_FUNCTIONS (8, 256.0f);
+CREATE_ARGB_FUNCTIONS (16, argb, 65536.0f, 0, 1, 2, 3);
+CREATE_ARGB_FUNCTIONS (8, argb, 256.0f, 0, 1, 2, 3);
+
+CREATE_ARGB_FUNCTIONS (16, bgra, 65536.0f, 3, 2, 1, 0);
+CREATE_ARGB_FUNCTIONS (8, bgra, 256.0f, 3, 2, 1, 0);
static GstFlowReturn
gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
@@ -937,6 +942,10 @@ gst_shape_wipe_video_sink_chain (GstPad * pad, GstBuffer * buffer)
ret = gst_shape_wipe_blend_argb_16 (self, buffer, mask, outbuf);
else if (self->fmt == GST_VIDEO_FORMAT_ARGB)
ret = gst_shape_wipe_blend_argb_8 (self, buffer, mask, outbuf);
+ else if (self->fmt == GST_VIDEO_FORMAT_BGRA && self->mask_bpp == 16)
+ ret = gst_shape_wipe_blend_bgra_16 (self, buffer, mask, outbuf);
+ else if (self->fmt == GST_VIDEO_FORMAT_BGRA)
+ ret = gst_shape_wipe_blend_bgra_8 (self, buffer, mask, outbuf);
else
g_assert_not_reached ();