mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
kate: add segment tracking, and various other improvements
https://bugzilla.gnome.org/show_bug.cgi?id=600929
This commit is contained in:
parent
4422cca1d3
commit
8574e8f991
10 changed files with 602 additions and 94 deletions
|
@ -10,7 +10,7 @@ endif
|
|||
|
||||
# flags used to compile this plugin
|
||||
libgstkate_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(TIGER_CFLAGS) $(KATE_CFLAGS)
|
||||
libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS)
|
||||
libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS)
|
||||
libgstkate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
|
||||
libgstkate_la_LIBTOOLFLAGS = --tag=disable-static
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ GST_DEBUG_CATEGORY (gst_katedec_debug);
|
|||
GST_DEBUG_CATEGORY (gst_kateenc_debug);
|
||||
GST_DEBUG_CATEGORY (gst_kateparse_debug);
|
||||
GST_DEBUG_CATEGORY (gst_katetag_debug);
|
||||
GST_DEBUG_CATEGORY (gst_kateutil_debug);
|
||||
#ifdef HAVE_TIGER
|
||||
GST_DEBUG_CATEGORY (gst_katetiger_debug);
|
||||
#endif
|
||||
|
@ -75,6 +76,8 @@ plugin_init (GstPlugin * plugin)
|
|||
GST_DEBUG_CATEGORY_INIT (gst_kateenc_debug, "kateenc", 0, "Kate encoder");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_kateparse_debug, "kateparse", 0, "Kate parser");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_katetag_debug, "katetag", 0, "Kate tagger");
|
||||
GST_DEBUG_CATEGORY_INIT (gst_kateutil_debug, "kateutil", 0,
|
||||
"Kate utility functions");
|
||||
#ifdef HAVE_TIGER
|
||||
GST_DEBUG_CATEGORY_INIT (gst_katetiger_debug, "tiger", 0,
|
||||
"Kate Tiger renderer");
|
||||
|
|
|
@ -128,6 +128,9 @@ static GstFlowReturn gst_kate_dec_chain (GstPad * pad, GstBuffer * buf);
|
|||
static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element,
|
||||
GstStateChange transition);
|
||||
static gboolean gst_kate_dec_sink_query (GstPad * pad, GstQuery * query);
|
||||
static gboolean gst_kate_dec_sink_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event);
|
||||
static GstCaps *gst_kate_dec_src_get_caps (GstPad * pad);
|
||||
|
||||
static void
|
||||
gst_kate_dec_base_init (gpointer gclass)
|
||||
|
@ -184,16 +187,21 @@ gst_kate_dec_init (GstKateDec * dec, GstKateDecClass * gclass)
|
|||
GST_DEBUG_FUNCPTR (gst_kate_dec_chain));
|
||||
gst_pad_set_query_function (dec->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_dec_sink_query));
|
||||
gst_pad_set_event_function (dec->sinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_dec_sink_event));
|
||||
gst_pad_use_fixed_caps (dec->sinkpad);
|
||||
gst_pad_set_caps (dec->sinkpad,
|
||||
gst_static_pad_template_get_caps (&sink_factory));
|
||||
gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
|
||||
|
||||
dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
||||
gst_pad_set_getcaps_function (dec->srcpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_dec_src_get_caps));
|
||||
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
|
||||
|
||||
gst_kate_util_decode_base_init (&dec->decoder);
|
||||
gst_kate_util_decode_base_init (&dec->decoder, TRUE);
|
||||
|
||||
dec->src_caps = NULL;
|
||||
dec->remove_markup = FALSE;
|
||||
}
|
||||
|
||||
|
@ -240,9 +248,16 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
|
|||
const kate_event *ev = NULL;
|
||||
GstFlowReturn rflow = GST_FLOW_OK;
|
||||
|
||||
if (!gst_kate_util_decoder_base_update_segment (&kd->decoder,
|
||||
GST_ELEMENT_CAST (kd), buf)) {
|
||||
GST_WARNING_OBJECT (kd, "Out of segment!");
|
||||
goto not_in_seg;
|
||||
}
|
||||
|
||||
rflow =
|
||||
gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder,
|
||||
GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, &ev);
|
||||
GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps,
|
||||
&ev);
|
||||
if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
|
||||
gst_object_unref (kd);
|
||||
gst_buffer_unref (buf);
|
||||
|
@ -336,6 +351,7 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
|
|||
}
|
||||
}
|
||||
|
||||
not_in_seg:
|
||||
gst_object_unref (kd);
|
||||
gst_buffer_unref (buf);
|
||||
return rflow;
|
||||
|
@ -345,6 +361,7 @@ static GstStateChangeReturn
|
|||
gst_kate_dec_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
GstKateDec *kd = GST_KATE_DEC (element);
|
||||
|
||||
return gst_kate_decoder_base_change_state (&kd->decoder, element,
|
||||
parent_class, transition);
|
||||
}
|
||||
|
@ -359,3 +376,87 @@ gst_kate_dec_sink_query (GstPad * pad, GstQuery * query)
|
|||
gst_object_unref (kd);
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_dec_sink_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (kd != NULL, FALSE);
|
||||
|
||||
GST_LOG_OBJECT (kd, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
// Delay events till we've set caps
|
||||
if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event,
|
||||
&gst_kate_dec_sink_handle_event, pad)) {
|
||||
gst_object_unref (kd);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = gst_kate_dec_sink_handle_event (pad, event);
|
||||
|
||||
gst_object_unref (kd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (kd != NULL, FALSE);
|
||||
|
||||
GST_LOG_OBJECT (kd, "Handling event on sink pad: %s",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
gst_kate_util_decoder_base_new_segment_event (&kd->decoder, event);
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
|
||||
case GST_EVENT_FLUSH_START:
|
||||
gst_kate_util_decoder_base_set_flushing (&kd->decoder, TRUE);
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
gst_kate_util_decoder_base_set_flushing (&kd->decoder, FALSE);
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
|
||||
default:
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
|
||||
gst_object_unref (kd);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_kate_dec_src_get_caps (GstPad * pad)
|
||||
{
|
||||
GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
GstCaps *caps;
|
||||
|
||||
g_return_val_if_fail (kd != NULL, FALSE);
|
||||
|
||||
if (kd->src_caps) {
|
||||
GST_DEBUG_OBJECT (kd, "We have src caps (%s)",
|
||||
gst_caps_to_string (kd->src_caps));
|
||||
caps = kd->src_caps;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (kd, "We have no src caps, using template caps");
|
||||
caps = gst_static_pad_template_get_caps (&src_factory);
|
||||
}
|
||||
|
||||
caps = gst_caps_copy (caps);
|
||||
|
||||
gst_object_unref (kd);
|
||||
return caps;
|
||||
}
|
||||
|
|
|
@ -67,12 +67,12 @@ typedef struct _GstKateDecClass GstKateDecClass;
|
|||
|
||||
struct _GstKateDec
|
||||
{
|
||||
GstElement element;
|
||||
GstKateDecoderBase decoder;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
GstKateDecoderBase decoder;
|
||||
GstCaps *src_caps;
|
||||
|
||||
gboolean remove_markup;
|
||||
};
|
||||
|
|
|
@ -255,11 +255,6 @@ gst_kate_parse_push_buffer (GstKateParse * parse, GstBuffer * buf,
|
|||
GST_BUFFER_OFFSET_END (buf) = granulepos;
|
||||
GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf);
|
||||
|
||||
/* Hack to flush each packet on its own page - taken off the CMML encoder element */
|
||||
/* TODO: this is shite and needs to go once I find a way to tell Ogg to flush
|
||||
as it messes up Matroska's track duration */
|
||||
GST_BUFFER_DURATION (buf) = G_MAXINT64;
|
||||
|
||||
gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
|
||||
|
||||
return gst_pad_push (parse->srcpad, buf);
|
||||
|
|
|
@ -804,14 +804,6 @@ gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev)
|
|||
bytes[nbytes++] =
|
||||
((kp->colors[palette[1]].a / 17) << 4) | (kp->colors[palette[0]].a / 17);
|
||||
|
||||
#if 0
|
||||
// move to top left - avoids a crash in dvdspu when overlaying on a small video :/
|
||||
right -= left;
|
||||
bottom -= top;
|
||||
left = 0;
|
||||
top = 0;
|
||||
#endif
|
||||
|
||||
CHKBUFSPC (7 * 2);
|
||||
bytes[nbytes++] = SPU_CMD_SET_DAREA;
|
||||
bytes[nbytes++] = left >> 4;
|
||||
|
|
|
@ -88,6 +88,19 @@
|
|||
GST_DEBUG_CATEGORY_EXTERN (gst_katetiger_debug);
|
||||
#define GST_CAT_DEFAULT gst_katetiger_debug
|
||||
|
||||
#define GST_KATE_TIGER_MUTEX_LOCK(element) \
|
||||
do { \
|
||||
/*GST_LOG_OBJECT ((element), "locking from %s:%d\n",__FILE__,__LINE__);*/ \
|
||||
g_mutex_lock ((element)->mutex); \
|
||||
/*GST_LOG_OBJECT ((element), "ready from %s:%d\n",__FILE__,__LINE__);*/ \
|
||||
} while(0)
|
||||
|
||||
#define GST_KATE_TIGER_MUTEX_UNLOCK(element) \
|
||||
do { \
|
||||
/*GST_LOG_OBJECT ((element), "unlocking from %s:%d\n",__FILE__,__LINE__);*/ \
|
||||
g_mutex_unlock ((element)->mutex); \
|
||||
} while(0)
|
||||
|
||||
/* Filter signals and args */
|
||||
enum
|
||||
{
|
||||
|
@ -119,16 +132,28 @@ static GstStaticPadTemplate kate_sink_factory =
|
|||
);
|
||||
|
||||
static GstStaticPadTemplate video_sink_factory =
|
||||
GST_STATIC_PAD_TEMPLATE ("video_sink",
|
||||
GST_STATIC_PAD_TEMPLATE ("video_sink",
|
||||
GST_PAD_SINK,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24")
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";"
|
||||
GST_VIDEO_CAPS_BGRx ", endianness = (int)4321")
|
||||
#else
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";"
|
||||
GST_VIDEO_CAPS_BGRx ", endianness = (int)1234")
|
||||
#endif
|
||||
);
|
||||
|
||||
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
|
||||
GST_PAD_SRC,
|
||||
GST_PAD_ALWAYS,
|
||||
GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24")
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";"
|
||||
GST_VIDEO_CAPS_BGRx ", endianness = (int)4321")
|
||||
#else
|
||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";"
|
||||
GST_VIDEO_CAPS_BGRx ", endianness = (int)1234")
|
||||
#endif
|
||||
);
|
||||
|
||||
GST_BOILERPLATE (GstKateTiger, gst_kate_tiger, GstElement, GST_TYPE_ELEMENT);
|
||||
|
@ -163,6 +188,7 @@ static GstStateChangeReturn gst_kate_tiger_change_state (GstElement * element,
|
|||
GstStateChange transition);
|
||||
static gboolean gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query);
|
||||
static gboolean gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_kate_tiger_video_event (GstPad * pad, GstEvent * event);
|
||||
static gboolean gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps);
|
||||
static gboolean gst_kate_tiger_source_event (GstPad * pad, GstEvent * event);
|
||||
|
||||
|
@ -302,19 +328,19 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass)
|
|||
gst_pad_new_from_static_template (&video_sink_factory, "video_sink");
|
||||
gst_pad_set_chain_function (tiger->videosinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_tiger_video_chain));
|
||||
//gst_pad_set_query_function (tiger->videosinkpad, GST_DEBUG_FUNCPTR (gst_kate_tiger_video_sink_query));
|
||||
gst_pad_use_fixed_caps (tiger->videosinkpad);
|
||||
gst_pad_set_caps (tiger->videosinkpad,
|
||||
gst_static_pad_template_get_caps (&video_sink_factory));
|
||||
gst_pad_set_setcaps_function (tiger->videosinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_tiger_video_set_caps));
|
||||
gst_pad_set_event_function (tiger->videosinkpad,
|
||||
GST_DEBUG_FUNCPTR (gst_kate_tiger_video_event));
|
||||
gst_element_add_pad (GST_ELEMENT (tiger), tiger->videosinkpad);
|
||||
|
||||
tiger->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
|
||||
gst_pad_set_event_function (tiger->srcpad, gst_kate_tiger_source_event);
|
||||
gst_pad_use_fixed_caps (tiger->srcpad);
|
||||
gst_element_add_pad (GST_ELEMENT (tiger), tiger->srcpad);
|
||||
|
||||
gst_kate_util_decode_base_init (&tiger->decoder);
|
||||
gst_kate_util_decode_base_init (&tiger->decoder, FALSE);
|
||||
|
||||
tiger->tr = NULL;
|
||||
|
||||
|
@ -400,7 +426,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id,
|
|||
GstKateTiger *tiger = GST_KATE_TIGER (object);
|
||||
const char *str;
|
||||
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_DEFAULT_FONT_DESC:
|
||||
|
@ -465,7 +491,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id,
|
|||
break;
|
||||
}
|
||||
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -474,7 +500,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id,
|
|||
{
|
||||
GstKateTiger *tiger = GST_KATE_TIGER (object);
|
||||
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_DEFAULT_FONT_DESC:
|
||||
|
@ -522,7 +548,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id,
|
|||
break;
|
||||
}
|
||||
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
}
|
||||
|
||||
/* GstElement vmethod implementations */
|
||||
|
@ -538,30 +564,36 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf)
|
|||
const kate_event *ev = NULL;
|
||||
GstFlowReturn rflow = GST_FLOW_OK;
|
||||
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
|
||||
GST_LOG_OBJECT (tiger, "Got kate buffer");
|
||||
GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s",
|
||||
gst_caps_to_string (GST_BUFFER_CAPS (buf)));
|
||||
|
||||
rflow =
|
||||
gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder,
|
||||
GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, &ev);
|
||||
if (G_LIKELY (rflow == GST_FLOW_OK)) {
|
||||
if (ev) {
|
||||
int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev);
|
||||
GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"",
|
||||
ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text);
|
||||
if (G_UNLIKELY (ret < 0)) {
|
||||
GST_WARNING_OBJECT (tiger,
|
||||
"failed to add Kate event to Tiger renderer: %d", ret);
|
||||
if (gst_kate_util_decoder_base_update_segment (&tiger->decoder,
|
||||
GST_ELEMENT_CAST (tiger), buf)) {
|
||||
GstPad *tagpad = gst_pad_get_peer (pad);
|
||||
rflow =
|
||||
gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder,
|
||||
GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, tagpad, NULL, &ev);
|
||||
if (G_LIKELY (rflow == GST_FLOW_OK)) {
|
||||
if (ev) {
|
||||
int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev);
|
||||
GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"",
|
||||
ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text);
|
||||
if (G_UNLIKELY (ret < 0)) {
|
||||
GST_WARNING_OBJECT (tiger,
|
||||
"failed to add Kate event to Tiger renderer: %d", ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_object_unref (tagpad);
|
||||
}
|
||||
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
|
||||
gst_object_unref (tiger);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
|
||||
return rflow;
|
||||
}
|
||||
|
||||
|
@ -569,28 +601,36 @@ static gboolean
|
|||
gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps)
|
||||
{
|
||||
GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad));
|
||||
GstStructure *s;
|
||||
GstVideoFormat format;
|
||||
gint w, h;
|
||||
gboolean res = FALSE;
|
||||
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
|
||||
s = gst_caps_get_structure (caps, 0);
|
||||
/* Cairo expects ARGB in native endianness, and that's what we get
|
||||
as we've forced it in the caps. We might allow swapped red/blue
|
||||
at some point, and get tiger to swap, to make some cases faster */
|
||||
tiger->swap_rgb = FALSE;
|
||||
|
||||
if (G_LIKELY (gst_structure_get_int (s, "width", &w))
|
||||
&& G_LIKELY (gst_structure_get_int (s, "height", &h))) {
|
||||
GST_INFO_OBJECT (tiger, "video sink: %d %d", w, h);
|
||||
if (gst_video_format_parse_caps (caps, &format, &w, &h)) {
|
||||
tiger->video_width = w;
|
||||
tiger->video_height = h;
|
||||
res = TRUE;
|
||||
}
|
||||
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
|
||||
gst_pad_set_caps (tiger->srcpad, caps);
|
||||
|
||||
gst_object_unref (tiger);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gst_kate_tiger_get_time (GstKateTiger * tiger)
|
||||
{
|
||||
return gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME,
|
||||
tiger->video_segment.last_stop) / (gdouble) GST_SECOND;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
|
||||
{
|
||||
|
@ -599,10 +639,22 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
|
|||
unsigned char *ptr;
|
||||
int ret;
|
||||
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
|
||||
GST_LOG_OBJECT (tiger, "got video frame, %u bytes", GST_BUFFER_SIZE (buf));
|
||||
|
||||
if (G_UNLIKELY (tiger->video_flushing)) {
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
gst_object_unref (tiger);
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_WRONG_STATE;
|
||||
}
|
||||
|
||||
if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
|
||||
gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME,
|
||||
GST_BUFFER_TIMESTAMP (buf));
|
||||
}
|
||||
|
||||
/* draw on it */
|
||||
buf = gst_buffer_make_writable (buf);
|
||||
if (G_UNLIKELY (!buf)) {
|
||||
|
@ -613,12 +665,17 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
|
|||
GST_WARNING_OBJECT (tiger,
|
||||
"Failed to get a pointer to video buffer data");
|
||||
} else {
|
||||
ret = tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, tiger->video_height, tiger->video_width * 4, 0); // TODO: stride ?
|
||||
ret =
|
||||
tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width,
|
||||
tiger->video_height, tiger->video_width * 4, tiger->swap_rgb);
|
||||
if (G_UNLIKELY (ret < 0)) {
|
||||
GST_WARNING_OBJECT (tiger,
|
||||
"Tiger renderer failed to set buffer to video frame: %d", ret);
|
||||
} else {
|
||||
kate_float t = GST_BUFFER_TIMESTAMP (buf) / (gdouble) GST_SECOND;
|
||||
kate_float t = gst_kate_tiger_get_time (tiger);
|
||||
GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f",
|
||||
(long) tiger->video_segment.last_stop, t);
|
||||
|
||||
ret = tiger_renderer_update (tiger->tr, t, 1);
|
||||
if (G_UNLIKELY (ret < 0)) {
|
||||
GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d",
|
||||
|
@ -636,12 +693,13 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
|
||||
rflow = gst_pad_push (tiger->srcpad, buf);
|
||||
|
||||
gst_object_unref (tiger);
|
||||
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
|
||||
return rflow;
|
||||
}
|
||||
|
||||
|
@ -654,12 +712,14 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
|
|||
switch (transition) {
|
||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||
GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state");
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
if (tiger->tr) {
|
||||
tiger_renderer_destroy (tiger->tr);
|
||||
tiger->tr = NULL;
|
||||
}
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
|
||||
tiger->video_flushing = TRUE;
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -672,7 +732,7 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
|
|||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
GST_DEBUG_OBJECT (tiger, "READY -> PAUSED, initializing kate state");
|
||||
g_mutex_lock (tiger->mutex);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
if (tiger->decoder.initialized) {
|
||||
int ret = tiger_renderer_create (&tiger->tr);
|
||||
if (ret < 0) {
|
||||
|
@ -692,7 +752,9 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition)
|
|||
gst_kate_tiger_update_quality (tiger);
|
||||
}
|
||||
}
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
|
||||
tiger->video_flushing = FALSE;
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -713,18 +775,42 @@ gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event)
|
|||
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
|
||||
&stop_type, &stop);
|
||||
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
tiger->video_flushing = TRUE;
|
||||
gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
/* if seeking in time, we can update tiger to remove any appropriate events */
|
||||
kate_float target;
|
||||
switch (cur_type) {
|
||||
case GST_SEEK_TYPE_SET:
|
||||
target = cur / (float) GST_SECOND;
|
||||
break;
|
||||
case GST_SEEK_TYPE_CUR:
|
||||
target = gst_kate_tiger_get_time (tiger) + cur / (float) GST_SECOND;
|
||||
break;
|
||||
case GST_SEEK_TYPE_END:
|
||||
GST_WARNING_OBJECT (tiger,
|
||||
"Seeking from the end, cannot work out target so flushing everything");
|
||||
target = (kate_float) 0;
|
||||
break;
|
||||
default:
|
||||
GST_WARNING_OBJECT (tiger, "Unexpected seek type");
|
||||
target = (kate_float) 0;
|
||||
break;
|
||||
}
|
||||
GST_INFO_OBJECT (tiger, "Seeking in time to %f", target);
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
tiger_renderer_seek (tiger->tr, target);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
}
|
||||
|
||||
/* forward to both sinks */
|
||||
gst_event_ref (event);
|
||||
if (gst_pad_push_event (tiger->videosinkpad, event)) {
|
||||
if (gst_pad_push_event (tiger->katesinkpad, event)) {
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
/* if seeking in time, we can update tiger to remove any appropriate events */
|
||||
kate_float target = cur / (gdouble) GST_SECOND;
|
||||
GST_INFO_OBJECT (tiger, "Seeking in time to %f", target);
|
||||
g_mutex_lock (tiger->mutex);
|
||||
tiger_renderer_seek (tiger->tr, target);
|
||||
g_mutex_unlock (tiger->mutex);
|
||||
}
|
||||
int ret = gst_pad_push_event (tiger->katesinkpad, event);
|
||||
if (ret) {
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
|
@ -744,6 +830,9 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event)
|
|||
|
||||
g_return_val_if_fail (tiger != NULL, FALSE);
|
||||
|
||||
GST_LOG_OBJECT (tiger, "Event on source pad: %s",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_SEEK:
|
||||
GST_INFO_OBJECT (tiger, "Seek on source pad");
|
||||
|
@ -759,6 +848,49 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event)
|
|||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstKateTiger *tiger =
|
||||
(GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
gboolean res = TRUE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
GST_INFO_OBJECT (tiger, "New segment on Kate pad");
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_START:
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_kate_util_decoder_base_set_flushing (&tiger->decoder, FALSE);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
/* we ignore this, it just means we don't have anymore Kate packets, but
|
||||
the Tiger renderer will still draw (if appropriate) on incoming video */
|
||||
GST_INFO_OBJECT (tiger, "EOS on Kate pad");
|
||||
gst_event_unref (event);
|
||||
break;
|
||||
default:
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
}
|
||||
|
||||
gst_object_unref (tiger);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
|
@ -768,16 +900,69 @@ gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
|
|||
|
||||
g_return_val_if_fail (tiger != NULL, FALSE);
|
||||
|
||||
GST_LOG_OBJECT (tiger, "Event on Kate pad: %s", GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
/* Delay events till we've set caps */
|
||||
if (gst_kate_util_decoder_base_queue_event (&tiger->decoder, event,
|
||||
&gst_kate_tiger_handle_kate_event, pad)) {
|
||||
gst_object_unref (tiger);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
res = gst_kate_tiger_handle_kate_event (pad, event);
|
||||
|
||||
gst_object_unref (tiger);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstKateTiger *tiger =
|
||||
(GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
gboolean res = TRUE;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_NEWSEGMENT:
|
||||
GST_INFO_OBJECT (tiger, "New segment on Kate pad");
|
||||
gst_event_unref (event);
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate, arate;
|
||||
GstFormat format;
|
||||
gint64 start, stop, time;
|
||||
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
|
||||
if (format == GST_FORMAT_TIME) {
|
||||
GST_DEBUG_OBJECT (tiger, "video pad segment:"
|
||||
" Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
|
||||
" %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT,
|
||||
update, rate, arate, format, GST_TIME_ARGS (start),
|
||||
GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
|
||||
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_segment_set_newsegment_full (&tiger->video_segment, update, rate,
|
||||
arate, format, start, stop, time);
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
}
|
||||
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
case GST_EVENT_EOS:
|
||||
/* we ignore this, it just means we don't have anymore Kate packets, but
|
||||
the Tiger renderer will still draw (if appropriate) on incoming video */
|
||||
GST_INFO_OBJECT (tiger, "EOS on Kate pad");
|
||||
gst_event_unref (event);
|
||||
}
|
||||
case GST_EVENT_FLUSH_START:
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
|
||||
tiger->video_flushing = TRUE;
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
GST_KATE_TIGER_MUTEX_LOCK (tiger);
|
||||
gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED);
|
||||
tiger->video_flushing = FALSE;
|
||||
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
|
||||
res = gst_pad_event_default (pad, event);
|
||||
break;
|
||||
default:
|
||||
res = gst_pad_event_default (pad, event);
|
||||
|
@ -789,12 +974,32 @@ gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event)
|
|||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_kate_tiger_video_event (GstPad * pad, GstEvent * event)
|
||||
{
|
||||
GstKateTiger *tiger =
|
||||
(GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad)));
|
||||
gboolean res = TRUE;
|
||||
|
||||
g_return_val_if_fail (tiger != NULL, FALSE);
|
||||
|
||||
GST_INFO_OBJECT (tiger, "Event on video pad: %s",
|
||||
GST_EVENT_TYPE_NAME (event));
|
||||
|
||||
res = gst_kate_tiger_handle_video_event (pad, event);
|
||||
|
||||
gst_object_unref (tiger);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query)
|
||||
{
|
||||
GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad));
|
||||
gboolean res = gst_kate_decoder_base_sink_query (&tiger->decoder,
|
||||
GST_ELEMENT_CAST (tiger), pad, query);
|
||||
GST_INFO_OBJECT (tiger, "Query on Kate pad");
|
||||
gst_object_unref (tiger);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -68,14 +68,12 @@ typedef struct _GstKateTigerClass GstKateTigerClass;
|
|||
|
||||
struct _GstKateTiger
|
||||
{
|
||||
GstElement element;
|
||||
GstKateDecoderBase decoder;
|
||||
|
||||
GstPad *katesinkpad;
|
||||
GstPad *videosinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
GstKateDecoderBase decoder;
|
||||
|
||||
tiger_renderer *tr;
|
||||
|
||||
gdouble quality;
|
||||
|
@ -93,8 +91,12 @@ struct _GstKateTiger
|
|||
|
||||
gint video_width;
|
||||
gint video_height;
|
||||
gboolean swap_rgb;
|
||||
|
||||
GMutex *mutex;
|
||||
|
||||
GstSegment video_segment;
|
||||
gboolean video_flushing;
|
||||
};
|
||||
|
||||
struct _GstKateTigerClass
|
||||
|
|
|
@ -23,10 +23,17 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <gst/tag/tag.h>
|
||||
#include "gstkate.h"
|
||||
#include "gstkateutil.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug);
|
||||
#define GST_CAT_DEFAULT gst_kateutil_debug
|
||||
|
||||
static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase *
|
||||
decoder);
|
||||
|
||||
GstCaps *
|
||||
gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps,
|
||||
GList * headers)
|
||||
|
@ -95,7 +102,8 @@ gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class)
|
|||
}
|
||||
|
||||
void
|
||||
gst_kate_util_decode_base_init (GstKateDecoderBase * decoder)
|
||||
gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
|
||||
gboolean delay_events)
|
||||
{
|
||||
if (G_UNLIKELY (!decoder))
|
||||
return;
|
||||
|
@ -106,6 +114,8 @@ gst_kate_util_decode_base_init (GstKateDecoderBase * decoder)
|
|||
decoder->original_canvas_height = 0;
|
||||
decoder->tags = NULL;
|
||||
decoder->initialized = FALSE;
|
||||
decoder->delay_events = delay_events;
|
||||
decoder->event_queue = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -121,9 +131,76 @@ gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder)
|
|||
}
|
||||
decoder->original_canvas_width = 0;
|
||||
decoder->original_canvas_height = 0;
|
||||
if (decoder->event_queue) {
|
||||
gst_kate_util_decoder_base_free_event_queue (decoder);
|
||||
}
|
||||
decoder->initialized = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder,
|
||||
GstEvent * event, gboolean (*handler) (GstPad *, GstEvent *), GstPad * pad)
|
||||
{
|
||||
gboolean can_be_queued;
|
||||
|
||||
switch (GST_EVENT_TYPE (event)) {
|
||||
case GST_EVENT_FLUSH_START:
|
||||
case GST_EVENT_FLUSH_STOP:
|
||||
case GST_EVENT_EOS:
|
||||
can_be_queued = FALSE;
|
||||
break;
|
||||
default:
|
||||
can_be_queued = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (decoder->delay_events && can_be_queued) {
|
||||
GstKateDecoderBaseQueuedEvent *item;
|
||||
GST_DEBUG_OBJECT (decoder, "We have to delay the event");
|
||||
item = g_slice_new (GstKateDecoderBaseQueuedEvent);
|
||||
if (item) {
|
||||
item->event = event;
|
||||
item->pad = pad;
|
||||
item->handler = handler;
|
||||
g_queue_push_tail (decoder->event_queue, item);
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder)
|
||||
{
|
||||
while (decoder->event_queue->length) {
|
||||
GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
|
||||
g_queue_pop_head (decoder->event_queue);
|
||||
g_slice_free (GstKateDecoderBaseQueuedEvent, item);
|
||||
}
|
||||
g_queue_free (decoder->event_queue);
|
||||
decoder->event_queue = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder)
|
||||
{
|
||||
decoder->delay_events = FALSE;
|
||||
|
||||
if (decoder->event_queue->length == 0)
|
||||
return;
|
||||
|
||||
GST_DEBUG_OBJECT (decoder, "We can now drain all events!");
|
||||
while (decoder->event_queue->length) {
|
||||
GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *)
|
||||
g_queue_pop_head (decoder->event_queue);
|
||||
(*item->handler) (item->pad, item->event);
|
||||
g_slice_free (GstKateDecoderBaseQueuedEvent, item);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
|
||||
GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
|
@ -152,38 +229,67 @@ gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder,
|
|||
GstFlowReturn
|
||||
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
|
||||
const kate_event ** ev)
|
||||
GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
|
||||
{
|
||||
kate_packet kp;
|
||||
int ret;
|
||||
GstFlowReturn rflow = GST_FLOW_OK;
|
||||
gboolean is_header;
|
||||
|
||||
GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
|
||||
GST_BUFFER_SIZE (buf),
|
||||
GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
|
||||
|
||||
is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80);
|
||||
|
||||
if (!is_header && decoder->tags) {
|
||||
/* after we've processed headers, send any tags before processing the data packet */
|
||||
GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (tagpad));
|
||||
gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
|
||||
decoder->tags = NULL;
|
||||
}
|
||||
|
||||
kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf));
|
||||
ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
|
||||
if (G_UNLIKELY (ret < 0)) {
|
||||
GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
|
||||
("Failed to decode Kate packet: %d", ret));
|
||||
return GST_FLOW_ERROR;
|
||||
} else if (G_UNLIKELY (ret > 0)) {
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (ret > 0)) {
|
||||
GST_DEBUG_OBJECT (element,
|
||||
"kate_high_decode_packetin has received EOS packet");
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
/* headers may be interesting to retrieve information from */
|
||||
if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0))
|
||||
if (G_UNLIKELY (is_header)) {
|
||||
switch (GST_BUFFER_DATA (buf)[0]) {
|
||||
GstCaps *caps;
|
||||
|
||||
case 0x80: /* ID header */
|
||||
GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
|
||||
decoder->k.ki->language, decoder->k.ki->category);
|
||||
caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
|
||||
gst_pad_set_caps (srcpad, caps);
|
||||
gst_caps_unref (caps);
|
||||
if (src_caps) {
|
||||
if (*src_caps) {
|
||||
gst_caps_unref (*src_caps);
|
||||
*src_caps = NULL;
|
||||
}
|
||||
if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
|
||||
strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
|
||||
*src_caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
|
||||
} else if (decoder->k.ki->text_markup_type == kate_markup_none) {
|
||||
*src_caps = gst_caps_new_simple ("text/plain", NULL);
|
||||
} else {
|
||||
*src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
|
||||
}
|
||||
GST_INFO_OBJECT (element, "Setting src caps to %s",
|
||||
gst_caps_to_string (*src_caps));
|
||||
if (!gst_pad_set_caps (srcpad, *src_caps)) {
|
||||
GST_ERROR_OBJECT (element,
|
||||
"Failed to renegotiate caps for pad %s:%s",
|
||||
GST_DEBUG_PAD_NAME (srcpad));
|
||||
}
|
||||
}
|
||||
if (decoder->k.ki->language && *decoder->k.ki->language) {
|
||||
GstTagList *old = decoder->tags, *tags = gst_tag_list_new ();
|
||||
if (tags) {
|
||||
|
@ -214,6 +320,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
|
|||
decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
|
||||
decoder->original_canvas_height = decoder->k.ki->original_canvas_height;
|
||||
|
||||
/* we can now send away any event we've delayed, as the src pad now has caps */
|
||||
gst_kate_util_decoder_base_drain_event_queue (decoder);
|
||||
|
||||
break;
|
||||
|
||||
case 0x81: /* Vorbis comments header */
|
||||
|
@ -247,8 +356,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
|
|||
if (old)
|
||||
gst_tag_list_free (old);
|
||||
|
||||
#if 0
|
||||
if (decoder->initialized) {
|
||||
gst_element_found_tags_for_pad (element, srcpad, decoder->tags);
|
||||
gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
|
||||
decoder->tags = NULL;
|
||||
} else {
|
||||
/* Only push them as messages for the time being. *
|
||||
|
@ -257,12 +367,14 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
|
|||
gst_message_new_tag (GST_OBJECT (element),
|
||||
gst_tag_list_copy (decoder->tags)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rflow;
|
||||
}
|
||||
|
@ -285,7 +397,10 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
|
|||
GST_WARNING_OBJECT (element, "failed to initialize kate state: %d",
|
||||
ret);
|
||||
}
|
||||
gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
|
||||
decoder->kate_flushing = FALSE;
|
||||
decoder->initialized = TRUE;
|
||||
decoder->event_queue = g_queue_new ();
|
||||
break;
|
||||
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
|
||||
break;
|
||||
|
@ -304,6 +419,8 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
|
|||
kate_high_decode_clear (&decoder->k);
|
||||
decoder->initialized = FALSE;
|
||||
}
|
||||
gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
|
||||
decoder->kate_flushing = TRUE;
|
||||
gst_kate_util_decode_base_reset (decoder);
|
||||
break;
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
|
@ -316,6 +433,73 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
|
|||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
|
||||
gboolean flushing)
|
||||
{
|
||||
decoder->kate_flushing = flushing;
|
||||
gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED);
|
||||
}
|
||||
|
||||
void
|
||||
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
|
||||
GstEvent * event)
|
||||
{
|
||||
gboolean update;
|
||||
gdouble rate;
|
||||
GstFormat format;
|
||||
gint64 start, stop, time;
|
||||
gdouble arate;
|
||||
|
||||
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
|
||||
&start, &stop, &time);
|
||||
GST_DEBUG_OBJECT (decoder, "kate pad segment:"
|
||||
" Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
|
||||
" %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT,
|
||||
update, rate, arate, format, GST_TIME_ARGS (start),
|
||||
GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
|
||||
gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate,
|
||||
arate, format, start, stop, time);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstBuffer * buf)
|
||||
{
|
||||
gint64 clip_start = 0, clip_stop = 0;
|
||||
gboolean in_seg;
|
||||
|
||||
if (decoder->kate_flushing) {
|
||||
GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
|
||||
GstClockTime stop;
|
||||
|
||||
if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf)))
|
||||
stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
|
||||
else
|
||||
stop = GST_CLOCK_TIME_NONE;
|
||||
|
||||
in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME,
|
||||
GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop);
|
||||
} else {
|
||||
in_seg = TRUE;
|
||||
}
|
||||
|
||||
if (in_seg) {
|
||||
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
||||
gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME,
|
||||
clip_start);
|
||||
}
|
||||
} else {
|
||||
GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored");
|
||||
}
|
||||
|
||||
return in_seg;
|
||||
}
|
||||
|
||||
static GstClockTime
|
||||
gst_kate_util_granule_time (kate_state * k, gint64 granulepos)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,15 @@ G_BEGIN_DECLS enum
|
|||
|
||||
typedef struct
|
||||
{
|
||||
GstEvent * event;
|
||||
gboolean (*handler)(GstPad *, GstEvent *);
|
||||
GstPad *pad;
|
||||
} GstKateDecoderBaseQueuedEvent;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstElement element;
|
||||
|
||||
kate_state k;
|
||||
|
||||
gboolean initialized;
|
||||
|
@ -49,11 +58,17 @@ typedef struct
|
|||
gint original_canvas_width;
|
||||
gint original_canvas_height;
|
||||
|
||||
GstSegment kate_segment;
|
||||
gboolean kate_flushing;
|
||||
|
||||
gboolean delay_events;
|
||||
GQueue *event_queue;
|
||||
} GstKateDecoderBase;
|
||||
|
||||
extern GstCaps *gst_kate_util_set_header_on_caps (GstElement * element,
|
||||
GstCaps * caps, GList * headers);
|
||||
extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder);
|
||||
extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder,
|
||||
gboolean delay_events);
|
||||
extern void gst_kate_util_install_decoder_base_properties (GObjectClass *
|
||||
gobject_class);
|
||||
extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase *
|
||||
|
@ -62,7 +77,16 @@ extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase *
|
|||
extern GstFlowReturn
|
||||
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstPad * pad, GstBuffer * buffer, GstPad * srcpad,
|
||||
const kate_event ** ev);
|
||||
GstPad * tagpad, GstCaps **src_caps, const kate_event ** ev);
|
||||
extern void
|
||||
gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
|
||||
gboolean flushing);
|
||||
extern void
|
||||
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
|
||||
GstEvent * event);
|
||||
extern gboolean
|
||||
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstBuffer * buf);
|
||||
extern GstStateChangeReturn
|
||||
gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstElementClass * parent_class,
|
||||
|
@ -72,6 +96,8 @@ extern gboolean gst_kate_decoder_base_convert (GstKateDecoderBase * decoder,
|
|||
GstFormat * dest_fmt, gint64 * dest_val);
|
||||
extern gboolean gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder,
|
||||
GstElement * element, GstPad * pad, GstQuery * query);
|
||||
extern gboolean
|
||||
gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, GstEvent * event, gboolean (*handler)(GstPad *, GstEvent *), GstPad * pad);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_KATE_UTIL_H__ */
|
||||
|
|
Loading…
Reference in a new issue