kate: port to 0.11

This commit is contained in:
Wim Taymans 2011-10-08 14:22:58 +02:00
parent 082fca4172
commit a9fc805e36
7 changed files with 200 additions and 212 deletions

View file

@ -117,7 +117,8 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS ("text/plain; text/x-pango-markup; " GST_KATE_SPU_MIME_TYPE) GST_STATIC_CAPS ("text/plain; text/x-pango-markup; " GST_KATE_SPU_MIME_TYPE)
); );
GST_BOILERPLATE (GstKateDec, gst_kate_dec, GstElement, GST_TYPE_ELEMENT); #define gst_kate_dec_parent_class parent_class
G_DEFINE_TYPE (GstKateDec, gst_kate_dec, GST_TYPE_ELEMENT);
static void gst_kate_dec_set_property (GObject * object, guint prop_id, static void gst_kate_dec_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec); const GValue * value, GParamSpec * pspec);
@ -130,23 +131,7 @@ static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element,
static gboolean gst_kate_dec_sink_query (GstPad * pad, GstQuery * query); 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_event (GstPad * pad, GstEvent * event);
static gboolean gst_kate_dec_sink_handle_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 GstCaps *gst_kate_dec_src_get_caps (GstPad * pad, GstCaps * filter);
static void
gst_kate_dec_base_init (gpointer gclass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (element_class,
"Kate stream text decoder", "Codec/Decoder/Subtitle",
"Decodes Kate text streams",
"Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
}
/* initialize the plugin's class */ /* initialize the plugin's class */
static void static void
@ -170,6 +155,16 @@ gst_kate_dec_class_init (GstKateDecClass * klass)
gstelement_class->change_state = gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_kate_dec_change_state); GST_DEBUG_FUNCPTR (gst_kate_dec_change_state);
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (gstelement_class,
"Kate stream text decoder", "Codec/Decoder/Subtitle",
"Decodes Kate text streams",
"Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
} }
/* initialize the new element /* initialize the new element
@ -178,7 +173,7 @@ gst_kate_dec_class_init (GstKateDecClass * klass)
* initialize structure * initialize structure
*/ */
static void static void
gst_kate_dec_init (GstKateDec * dec, GstKateDecClass * gclass) gst_kate_dec_init (GstKateDec * dec)
{ {
GST_DEBUG_OBJECT (dec, "gst_kate_dec_init"); GST_DEBUG_OBJECT (dec, "gst_kate_dec_init");
@ -295,11 +290,10 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
if (G_LIKELY (buffer)) { if (G_LIKELY (buffer)) {
const char *mime = plain ? "text/plain" : "text/x-pango-markup"; const char *mime = plain ? "text/plain" : "text/x-pango-markup";
GstCaps *caps = gst_caps_new_simple (mime, NULL); GstCaps *caps = gst_caps_new_simple (mime, NULL);
gst_buffer_set_caps (buffer, caps);
gst_caps_unref (caps); gst_caps_unref (caps);
/* allocate and copy the NULs, but don't include them in passed size */ /* allocate and copy the NULs, but don't include them in passed size */
memcpy (GST_BUFFER_DATA (buffer), escaped, len + 1); gst_buffer_fill (buffer, 0, escaped, len + 1);
GST_BUFFER_SIZE (buffer) = len; gst_buffer_resize (buffer, 0, len);
GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND; GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND;
GST_BUFFER_DURATION (buffer) = GST_BUFFER_DURATION (buffer) =
(ev->end_time - ev->start_time) * GST_SECOND; (ev->end_time - ev->start_time) * GST_SECOND;
@ -330,9 +324,6 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
if (ev->bitmap && ev->palette) { if (ev->bitmap && ev->palette) {
GstBuffer *buffer = gst_kate_spu_encode_spu (kd, ev); GstBuffer *buffer = gst_kate_spu_encode_spu (kd, ev);
if (buffer) { if (buffer) {
GstCaps *caps = gst_caps_new_simple (GST_KATE_SPU_MIME_TYPE, NULL);
gst_buffer_set_caps (buffer, caps);
gst_caps_unref (caps);
GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND; GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND;
GST_BUFFER_DURATION (buffer) = GST_BUFFER_DURATION (buffer) =
(ev->end_time - ev->start_time) * GST_SECOND; (ev->end_time - ev->start_time) * GST_SECOND;
@ -416,8 +407,8 @@ gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event)
GST_EVENT_TYPE_NAME (event)); GST_EVENT_TYPE_NAME (event));
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_SEGMENT:
gst_kate_util_decoder_base_new_segment_event (&kd->decoder, event); gst_kate_util_decoder_base_segment_event (&kd->decoder, event);
res = gst_pad_event_default (pad, event); res = gst_pad_event_default (pad, event);
break; break;
@ -442,7 +433,7 @@ gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event)
} }
static GstCaps * static GstCaps *
gst_kate_dec_src_get_caps (GstPad * pad) gst_kate_dec_src_get_caps (GstPad * pad, GstCaps * filter)
{ {
GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad)));
GstCaps *caps; GstCaps *caps;

View file

@ -142,26 +142,10 @@ static GstStateChangeReturn gst_kate_enc_change_state (GstElement * element,
static gboolean gst_kate_enc_sink_event (GstPad * pad, GstEvent * event); static gboolean gst_kate_enc_sink_event (GstPad * pad, GstEvent * event);
static const GstQueryType *gst_kate_enc_source_query_type (GstPad * pad); static const GstQueryType *gst_kate_enc_source_query_type (GstPad * pad);
static gboolean gst_kate_enc_source_query (GstPad * pad, GstQuery * query); static gboolean gst_kate_enc_source_query (GstPad * pad, GstQuery * query);
static void gst_kate_enc_add_interfaces (GType kateenc_type);
GST_BOILERPLATE_FULL (GstKateEnc, gst_kate_enc, GstElement, #define gst_kate_enc_parent_class parent_class
GST_TYPE_ELEMENT, gst_kate_enc_add_interfaces); G_DEFINE_TYPE_WITH_CODE (GstKateEnc, gst_kate_enc, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
static void
gst_kate_enc_base_init (gpointer gclass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&sink_factory));
gst_element_class_set_details_simple (element_class, "Kate stream encoder",
"Codec/Encoder/Subtitle",
"Encodes Kate streams from text or subpictures",
"Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
}
/* initialize the plugin's class */ /* initialize the plugin's class */
static void static void
@ -173,8 +157,6 @@ gst_kate_enc_class_init (GstKateEncClass * klass)
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_enc_set_property); gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_enc_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_enc_get_property); gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_enc_get_property);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_enc_dispose); gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_kate_enc_dispose);
@ -228,15 +210,16 @@ gst_kate_enc_class_init (GstKateEncClass * klass)
gstelement_class->change_state = gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_kate_enc_change_state); GST_DEBUG_FUNCPTR (gst_kate_enc_change_state);
}
static void gst_element_class_add_pad_template (gstelement_class,
gst_kate_enc_add_interfaces (GType kateenc_type) gst_static_pad_template_get (&src_factory));
{ gst_element_class_add_pad_template (gstelement_class,
static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL }; gst_static_pad_template_get (&sink_factory));
g_type_add_interface_static (kateenc_type, GST_TYPE_TAG_SETTER, gst_element_class_set_details_simple (gstelement_class, "Kate stream encoder",
&tag_setter_info); "Codec/Encoder/Subtitle",
"Encodes Kate streams from text or subpictures",
"Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
} }
/* initialize the new element /* initialize the new element
@ -245,7 +228,7 @@ gst_kate_enc_add_interfaces (GType kateenc_type)
* initialize structure * initialize structure
*/ */
static void static void
gst_kate_enc_init (GstKateEnc * ke, GstKateEncClass * gclass) gst_kate_enc_init (GstKateEnc * ke)
{ {
GST_DEBUG_OBJECT (ke, "gst_kate_enc_init"); GST_DEBUG_OBJECT (ke, "gst_kate_enc_init");
@ -254,8 +237,6 @@ gst_kate_enc_init (GstKateEnc * ke, GstKateEncClass * gclass)
GST_DEBUG_FUNCPTR (gst_kate_enc_chain)); GST_DEBUG_FUNCPTR (gst_kate_enc_chain));
gst_pad_set_event_function (ke->sinkpad, gst_pad_set_event_function (ke->sinkpad,
GST_DEBUG_FUNCPTR (gst_kate_enc_sink_event)); GST_DEBUG_FUNCPTR (gst_kate_enc_sink_event));
gst_pad_set_setcaps_function (ke->sinkpad,
GST_DEBUG_FUNCPTR (gst_kate_enc_setcaps));
gst_element_add_pad (GST_ELEMENT (ke), ke->sinkpad); gst_element_add_pad (GST_ELEMENT (ke), ke->sinkpad);
ke->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); ke->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
@ -410,14 +391,14 @@ gst_kate_enc_create_buffer (GstKateEnc * ke, kate_packet * kp,
g_return_val_if_fail (kp != NULL, NULL); g_return_val_if_fail (kp != NULL, NULL);
g_return_val_if_fail (kp->data != NULL, NULL); g_return_val_if_fail (kp->data != NULL, NULL);
buffer = gst_buffer_try_new_and_alloc (kp->nbytes); buffer = gst_buffer_new_allocate (NULL, kp->nbytes, 0);
if (G_UNLIKELY (!buffer)) { if (G_UNLIKELY (!buffer)) {
GST_WARNING_OBJECT (ke, "Failed to allocate buffer for %u bytes", GST_WARNING_OBJECT (ke, "Failed to allocate buffer for %u bytes",
(guint) kp->nbytes); (guint) kp->nbytes);
return NULL; return NULL;
} }
memcpy (GST_BUFFER_DATA (buffer), kp->data, kp->nbytes); gst_buffer_fill (buffer, 0, kp->data, kp->nbytes);
/* same system as other Ogg codecs, as per ext/ogg/README: /* same system as other Ogg codecs, as per ext/ogg/README:
OFFSET_END is the granulepos OFFSET_END is the granulepos
@ -644,16 +625,6 @@ gst_kate_enc_send_headers (GstKateEnc * ke)
if (caps) { if (caps) {
GST_DEBUG_OBJECT (ke, "here are the caps: %" GST_PTR_FORMAT, caps); GST_DEBUG_OBJECT (ke, "here are the caps: %" GST_PTR_FORMAT, caps);
gst_pad_set_caps (ke->srcpad, caps); gst_pad_set_caps (ke->srcpad, caps);
GST_LOG_OBJECT (ke, "setting caps on headers");
item = headers;
while (item) {
GstBuffer *buffer = item->data;
GST_LOG_OBJECT (ke, "settings caps on header %p", buffer);
gst_buffer_set_caps (buffer, caps);
item = item->next;
}
gst_caps_unref (caps); gst_caps_unref (caps);
GST_LOG_OBJECT (ke, "pushing headers"); GST_LOG_OBJECT (ke, "pushing headers");
@ -869,7 +840,7 @@ gst_kate_enc_chain_spu (GstKateEnc * ke, GstBuffer * buf)
#endif #endif
GST_DEBUG_OBJECT (ke, "Encoding %ux%u SPU: (%u bytes) from %f to %f", GST_DEBUG_OBJECT (ke, "Encoding %ux%u SPU: (%u bytes) from %f to %f",
(guint) kbitmap->width, (guint) kbitmap->height, (guint) kbitmap->width, (guint) kbitmap->height,
GST_BUFFER_SIZE (buf), t0, t1); gst_buffer_get_size (buf), t0, t1);
ret = kate_encode_set_region (&ke->k, kregion); ret = kate_encode_set_region (&ke->k, kregion);
if (G_UNLIKELY (ret < 0)) { if (G_UNLIKELY (ret < 0)) {
@ -953,15 +924,18 @@ gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf,
("kate_encode_set_markup_type: %d", ret)); ("kate_encode_set_markup_type: %d", ret));
rflow = GST_FLOW_ERROR; rflow = GST_FLOW_ERROR;
} else { } else {
const char *text = (const char *) GST_BUFFER_DATA (buf); char *text;
gsize text_len;
text = gst_buffer_map (buf, &text_len, NULL, GST_MAP_READ);
if (text) { if (text) {
size_t text_len = GST_BUFFER_SIZE (buf);
kate_float t0 = start / (double) GST_SECOND; kate_float t0 = start / (double) GST_SECOND;
kate_float t1 = stop / (double) GST_SECOND; kate_float t1 = stop / (double) GST_SECOND;
GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f", GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f",
(int) text_len, (int) text_len, GST_BUFFER_DATA (buf), (int) text_len, (int) text_len, text, text_len, t0, t1);
GST_BUFFER_SIZE (buf), t0, t1);
ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp); ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp);
if (G_UNLIKELY (ret < 0)) { if (G_UNLIKELY (ret < 0)) {
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Failed to encode text: %d", ret)); ("Failed to encode text: %d", ret));
@ -976,6 +950,7 @@ gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf,
("no text in text packet")); ("no text in text packet"));
rflow = GST_FLOW_ERROR; rflow = GST_FLOW_ERROR;
} }
gst_buffer_unmap (buf, text, text_len);
} }
return rflow; return rflow;
@ -992,10 +967,10 @@ gst_kate_enc_chain (GstPad * pad, GstBuffer * buf)
GstCaps *caps; GstCaps *caps;
const gchar *mime_type = NULL; const gchar *mime_type = NULL;
GST_DEBUG_OBJECT (ke, "got packet, %u bytes", GST_BUFFER_SIZE (buf)); GST_DEBUG_OBJECT (ke, "got packet, %u bytes", gst_buffer_get_size (buf));
/* get the type of the data we're being sent */ /* get the type of the data we're being sent */
caps = GST_PAD_CAPS (pad); caps = gst_pad_get_current_caps (pad);
if (G_UNLIKELY (caps == NULL)) { if (G_UNLIKELY (caps == NULL)) {
GST_WARNING_OBJECT (ke, "No input caps set"); GST_WARNING_OBJECT (ke, "No input caps set");
rflow = GST_FLOW_NOT_NEGOTIATED; rflow = GST_FLOW_NOT_NEGOTIATED;
@ -1027,6 +1002,7 @@ gst_kate_enc_chain (GstPad * pad, GstBuffer * buf)
} else { } else {
GST_WARNING_OBJECT (ke, "Packet has no MIME type, ignored"); GST_WARNING_OBJECT (ke, "Packet has no MIME type, ignored");
} }
gst_caps_unref (caps);
} }
gst_buffer_unref (buf); gst_buffer_unref (buf);
@ -1261,38 +1237,46 @@ static gboolean
gst_kate_enc_sink_event (GstPad * pad, GstEvent * event) gst_kate_enc_sink_event (GstPad * pad, GstEvent * event)
{ {
GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad)); GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad));
GstStructure *structure; const GstStructure *structure;
gboolean ret; gboolean ret;
switch (GST_EVENT_TYPE (event)) { switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT: case GST_EVENT_CAPS:
{
GstCaps *caps;
gst_event_parse_caps (event, &caps);
ret = gst_kate_enc_setcaps (pad, caps);
gst_event_unref (event);
break;
}
case GST_EVENT_SEGMENT:
GST_LOG_OBJECT (ke, "Got newsegment event"); GST_LOG_OBJECT (ke, "Got newsegment event");
if (ke->initialized) { if (ke->initialized) {
GST_LOG_OBJECT (ke, "ensuring all headers are in"); GST_LOG_OBJECT (ke, "ensuring all headers are in");
if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) { if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
GST_WARNING_OBJECT (ke, "Failed to flush headers"); GST_WARNING_OBJECT (ke, "Failed to flush headers");
} else { } else {
GstFormat format; GstSegment seg;
gint64 timestamp;
gst_event_parse_new_segment (event, NULL, NULL, &format, &timestamp, gst_event_copy_segment (event, &seg);
NULL, NULL); if (seg.format != GST_FORMAT_TIME
if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (timestamp)) { || !GST_CLOCK_TIME_IS_VALID (seg.start)) {
GST_WARNING_OBJECT (ke, GST_WARNING_OBJECT (ke,
"No time in newsegment event %p, format %d, timestamp %" "No time in newsegment event %p, format %d, timestamp %"
G_GINT64_FORMAT, event, (int) format, timestamp); G_GINT64_FORMAT, event, (int) seg.format, seg.start);
/* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a /* to be safe, we'd need to generate a keepalive anyway, but we'd have to guess at the timestamp to use; a
good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a good guess would be the last known timestamp plus the keepalive time, but if we then get a packet with a
timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we timestamp less than this, it would fail to encode, which would be Bad. If we don't encode a keepalive, we
run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */ run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */
} else { } else {
float t = timestamp / (double) GST_SECOND; float t = seg.start / (double) GST_SECOND;
if (ke->delayed_spu if (ke->delayed_spu
&& t - ke->delayed_start / (double) GST_SECOND >= && t - ke->delayed_start / (double) GST_SECOND >=
ke->default_spu_duration) { ke->default_spu_duration) {
if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke, if (G_UNLIKELY (gst_kate_enc_flush_waiting (ke,
timestamp) != GST_FLOW_OK)) { seg.start) != GST_FLOW_OK)) {
GST_WARNING_OBJECT (ke, "Failed to encode delayed packet"); GST_WARNING_OBJECT (ke, "Failed to encode delayed packet");
/* continue with new segment handling anyway */ /* continue with new segment handling anyway */
} }
@ -1307,7 +1291,7 @@ gst_kate_enc_sink_event (GstPad * pad, GstEvent * event)
/* we only generate a keepalive if there is no SPU waiting, as it would /* we only generate a keepalive if there is no SPU waiting, as it would
mean out of sequence start times - and granulepos */ mean out of sequence start times - and granulepos */
if (!ke->delayed_spu) { if (!ke->delayed_spu) {
gst_kate_enc_generate_keepalive (ke, timestamp); gst_kate_enc_generate_keepalive (ke, seg.start);
} }
} }
} }
@ -1319,7 +1303,7 @@ gst_kate_enc_sink_event (GstPad * pad, GstEvent * event)
case GST_EVENT_CUSTOM_DOWNSTREAM: case GST_EVENT_CUSTOM_DOWNSTREAM:
GST_LOG_OBJECT (ke, "Got custom downstream event"); GST_LOG_OBJECT (ke, "Got custom downstream event");
/* adapted from the dvdsubdec element */ /* adapted from the dvdsubdec element */
structure = event->structure; structure = gst_event_get_structure (event);
if (structure != NULL if (structure != NULL
&& gst_structure_has_name (structure, "application/x-gst-dvd")) { && gst_structure_has_name (structure, "application/x-gst-dvd")) {
if (ke->initialized) { if (ke->initialized) {

View file

@ -83,7 +83,8 @@ static GstStaticPadTemplate gst_kate_parse_src_factory =
GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate")
); );
GST_BOILERPLATE (GstKateParse, gst_kate_parse, GstElement, GST_TYPE_ELEMENT); #define gst_kate_parse_parent_class parent_class
G_DEFINE_TYPE (GstKateParse, gst_kate_parse, GST_TYPE_ELEMENT);
static GstFlowReturn gst_kate_parse_chain (GstPad * pad, GstBuffer * buffer); static GstFlowReturn gst_kate_parse_chain (GstPad * pad, GstBuffer * buffer);
static GstStateChangeReturn gst_kate_parse_change_state (GstElement * element, static GstStateChangeReturn gst_kate_parse_change_state (GstElement * element,
@ -98,21 +99,6 @@ static gboolean gst_kate_parse_convert (GstPad * pad,
static GstFlowReturn gst_kate_parse_parse_packet (GstKateParse * parse, static GstFlowReturn gst_kate_parse_parse_packet (GstKateParse * parse,
GstBuffer * buf); GstBuffer * buf);
static void
gst_kate_parse_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_kate_parse_src_factory));
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_kate_parse_sink_factory));
gst_element_class_set_details_simple (element_class, "Kate stream parser",
"Codec/Parser/Subtitle",
"parse raw kate streams",
"Vincent Penquerc'h <ogg.k.ogg.k at googlemail dot com>");
}
static void static void
gst_kate_parse_class_init (GstKateParseClass * klass) gst_kate_parse_class_init (GstKateParseClass * klass)
{ {
@ -120,11 +106,21 @@ gst_kate_parse_class_init (GstKateParseClass * klass)
gstelement_class->change_state = gst_kate_parse_change_state; gstelement_class->change_state = gst_kate_parse_change_state;
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_kate_parse_src_factory));
gst_element_class_add_pad_template (gstelement_class,
gst_static_pad_template_get (&gst_kate_parse_sink_factory));
gst_element_class_set_details_simple (gstelement_class, "Kate stream parser",
"Codec/Parser/Subtitle",
"parse raw kate streams",
"Vincent Penquerc'h <ogg.k.ogg.k at googlemail dot com>");
klass->parse_packet = GST_DEBUG_FUNCPTR (gst_kate_parse_parse_packet); klass->parse_packet = GST_DEBUG_FUNCPTR (gst_kate_parse_parse_packet);
} }
static void static void
gst_kate_parse_init (GstKateParse * parse, GstKateParseClass * g_class) gst_kate_parse_init (GstKateParse * parse)
{ {
parse->sinkpad = parse->sinkpad =
gst_pad_new_from_static_template (&gst_kate_parse_sink_factory, "sink"); gst_pad_new_from_static_template (&gst_kate_parse_sink_factory, "sink");
@ -166,7 +162,7 @@ gst_kate_parse_push_headers (GstKateParse * parse)
/* get the headers into the caps, passing them to kate as we go */ /* get the headers into the caps, passing them to kate as we go */
caps = caps =
gst_kate_util_set_header_on_caps (&parse->element, gst_kate_util_set_header_on_caps (&parse->element,
gst_pad_get_negotiated_caps (parse->sinkpad), parse->streamheader); gst_pad_get_current_caps (parse->sinkpad), parse->streamheader);
if (G_UNLIKELY (!caps)) { if (G_UNLIKELY (!caps)) {
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL),
@ -184,13 +180,18 @@ gst_kate_parse_push_headers (GstKateParse * parse)
headers = parse->streamheader; headers = parse->streamheader;
while (headers) { while (headers) {
guint8 *data;
gsize size;
outbuf = GST_BUFFER_CAST (headers->data); outbuf = GST_BUFFER_CAST (headers->data);
kate_packet_wrap (&packet, GST_BUFFER_SIZE (outbuf),
GST_BUFFER_DATA (outbuf)); data = gst_buffer_map (outbuf, &size, NULL, GST_MAP_READ);
kate_packet_wrap (&packet, size, data);
ret = kate_decode_headerin (&parse->ki, &parse->kc, &packet); ret = kate_decode_headerin (&parse->ki, &parse->kc, &packet);
if (G_UNLIKELY (ret < 0)) { if (G_UNLIKELY (ret < 0)) {
GST_WARNING_OBJECT (parse, "kate_decode_headerin returned %d", ret); GST_WARNING_OBJECT (parse, "kate_decode_headerin returned %d", ret);
} }
gst_buffer_unmap (outbuf, data, size);
/* takes ownership of outbuf, which was previously in parse->streamheader */ /* takes ownership of outbuf, which was previously in parse->streamheader */
outbuf_list = g_list_append (outbuf_list, outbuf); outbuf_list = g_list_append (outbuf_list, outbuf);
headers = headers->next; headers = headers->next;
@ -203,7 +204,6 @@ gst_kate_parse_push_headers (GstKateParse * parse)
headers = outbuf_list; headers = outbuf_list;
while (headers) { while (headers) {
outbuf = GST_BUFFER_CAST (headers->data); outbuf = GST_BUFFER_CAST (headers->data);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (parse->srcpad));
gst_pad_push (parse->srcpad, outbuf); gst_pad_push (parse->srcpad, outbuf);
headers = headers->next; headers = headers->next;
} }
@ -255,8 +255,6 @@ gst_kate_parse_push_buffer (GstKateParse * parse, GstBuffer * buf,
GST_BUFFER_OFFSET_END (buf) = granulepos; GST_BUFFER_OFFSET_END (buf) = granulepos;
GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf); GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf);
gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
return gst_pad_push (parse->srcpad, buf); return gst_pad_push (parse->srcpad, buf);
} }
@ -318,7 +316,7 @@ gst_kate_parse_queue_buffer (GstKateParse * parse, GstBuffer * buf)
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gint64 granpos; gint64 granpos;
buf = gst_buffer_make_metadata_writable (buf); buf = gst_buffer_make_writable (buf);
/* oggdemux stores the granule pos in the offset end */ /* oggdemux stores the granule pos in the offset end */
granpos = GST_BUFFER_OFFSET_END (buf); granpos = GST_BUFFER_OFFSET_END (buf);
@ -347,17 +345,20 @@ static GstFlowReturn
gst_kate_parse_parse_packet (GstKateParse * parse, GstBuffer * buf) gst_kate_parse_parse_packet (GstKateParse * parse, GstBuffer * buf)
{ {
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
guint8 header[1];
gsize size;
g_assert (parse); g_assert (parse);
parse->packetno++; parse->packetno++;
GST_LOG_OBJECT (parse, "Got packet %02x, %u bytes", size = gst_buffer_extract (buf, 0, header, 1);
GST_BUFFER_SIZE (buf) ? GST_BUFFER_DATA (buf)[0] : -1,
GST_BUFFER_SIZE (buf));
if (GST_BUFFER_SIZE (buf) > 0 && GST_BUFFER_DATA (buf)[0] & 0x80) { GST_LOG_OBJECT (parse, "Got packet %02x, %u bytes",
GST_DEBUG_OBJECT (parse, "Found header %02x", GST_BUFFER_DATA (buf)[0]); size ? header[0] : -1, gst_buffer_get_size (buf));
if (size > 0 && header[0] & 0x80) {
GST_DEBUG_OBJECT (parse, "Found header %02x", header[0]);
/* if 0x80 is set, it's streamheader, /* if 0x80 is set, it's streamheader,
* so put it on the streamheader list and return */ * so put it on the streamheader list and return */
parse->streamheader = g_list_append (parse->streamheader, buf); parse->streamheader = g_list_append (parse->streamheader, buf);
@ -387,7 +388,7 @@ gst_kate_parse_chain (GstPad * pad, GstBuffer * buffer)
g_assert (klass->parse_packet != NULL); g_assert (klass->parse_packet != NULL);
if (G_UNLIKELY (GST_PAD_CAPS (pad) == NULL)) if (G_UNLIKELY (!gst_pad_has_current_caps (pad)))
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
return klass->parse_packet (parse, buffer); return klass->parse_packet (parse, buffer);
@ -602,7 +603,7 @@ gst_kate_parse_change_state (GstElement * element, GstStateChange transition)
break; break;
} }
ret = parent_class->change_state (element, transition); ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:

View file

@ -276,17 +276,17 @@ gst_kate_spu_decode_command_sequence (GstKateEnc * ke, GstBuffer * buf,
guint16 date; guint16 date;
guint16 next_command_sequence; guint16 next_command_sequence;
const guint8 *ptr; const guint8 *ptr;
guint8 *data;
guint16 sz; guint16 sz;
gsize size;
if (command_sequence_offset >= GST_BUFFER_SIZE (buf)) { data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
GST_ELEMENT_ERROR (ke, STREAM, DECODE, (NULL),
("Command sequence offset %u is out of range %u",
command_sequence_offset, GST_BUFFER_SIZE (buf)));
return GST_FLOW_ERROR;
}
ptr = GST_BUFFER_DATA (buf) + command_sequence_offset; if (command_sequence_offset >= size)
sz = GST_BUFFER_SIZE (buf) - command_sequence_offset; goto out_of_range;
ptr = data + command_sequence_offset;
sz = size - command_sequence_offset;
GST_DEBUG_OBJECT (ke, "Decoding command sequence at %u (%u bytes)", GST_DEBUG_OBJECT (ke, "Decoding command sequence at %u (%u bytes)",
command_sequence_offset, sz); command_sequence_offset, sz);
@ -353,21 +353,35 @@ gst_kate_spu_decode_command_sequence (GstKateEnc * ke, GstBuffer * buf,
if (next_command_sequence != command_sequence_offset) { if (next_command_sequence != command_sequence_offset) {
GST_DEBUG_OBJECT (ke, "Jumping to next sequence at offset %u", GST_DEBUG_OBJECT (ke, "Jumping to next sequence at offset %u",
next_command_sequence); next_command_sequence);
gst_buffer_unmap (buf, data, size);
return gst_kate_spu_decode_command_sequence (ke, buf, return gst_kate_spu_decode_command_sequence (ke, buf,
next_command_sequence); next_command_sequence);
} else { } else {
gst_buffer_unmap (buf, data, size);
GST_DEBUG_OBJECT (ke, "No more sequences to decode"); GST_DEBUG_OBJECT (ke, "No more sequences to decode");
return GST_FLOW_OK; return GST_FLOW_OK;
} }
break; break;
default: default:
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Invalid SPU command: %u", cmd)); ("Invalid SPU command: %u", cmd));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
} }
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Error parsing SPU")); GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Error parsing SPU"));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
/* ERRORS */
out_of_range:
{
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, DECODE, (NULL),
("Command sequence offset %u is out of range %u",
command_sequence_offset, size));
return GST_FLOW_ERROR;
}
} }
static inline int static inline int
@ -451,8 +465,10 @@ GstFlowReturn
gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr, gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
kate_bitmap * kb, kate_palette * kp) kate_bitmap * kb, kate_palette * kp)
{ {
const guint8 *ptr = GST_BUFFER_DATA (buf); guint8 *data;
size_t sz = GST_BUFFER_SIZE (buf); gsize size;
const guint8 *ptr;
size_t sz;
guint16 packet_size; guint16 packet_size;
guint16 x, y; guint16 x, y;
size_t n; size_t n;
@ -463,6 +479,11 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
guint16 next_command_sequence; guint16 next_command_sequence;
guint16 code; guint16 code;
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
ptr = data;
sz = size;
/* before decoding anything, initialize to sensible defaults */ /* before decoding anything, initialize to sensible defaults */
memset (ke->spu_colormap, 0, sizeof (ke->spu_colormap)); memset (ke->spu_colormap, 0, sizeof (ke->spu_colormap));
memset (ke->spu_alpha, 0, sizeof (ke->spu_alpha)); memset (ke->spu_alpha, 0, sizeof (ke->spu_alpha));
@ -476,19 +497,21 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
packet_size = GST_KATE_UINT16_BE (ptr); packet_size = GST_KATE_UINT16_BE (ptr);
ADVANCE (2); ADVANCE (2);
GST_DEBUG_OBJECT (ke, "packet size %u (GstBuffer size %u)", packet_size, GST_DEBUG_OBJECT (ke, "packet size %u (GstBuffer size %u)", packet_size,
GST_BUFFER_SIZE (buf)); size);
CHECK (2); CHECK (2);
next_command_sequence = GST_KATE_UINT16_BE (ptr); next_command_sequence = GST_KATE_UINT16_BE (ptr);
ADVANCE (2); ADVANCE (2);
ptr = GST_BUFFER_DATA (buf) + next_command_sequence; ptr = data + next_command_sequence;
sz = GST_BUFFER_SIZE (buf) - next_command_sequence; sz = size - next_command_sequence;
GST_DEBUG_OBJECT (ke, "next command sequence at %u for %u", GST_DEBUG_OBJECT (ke, "next command sequence at %u for %u",
next_command_sequence, (guint) sz); next_command_sequence, (guint) sz);
rflow = gst_kate_spu_decode_command_sequence (ke, buf, next_command_sequence); rflow = gst_kate_spu_decode_command_sequence (ke, buf, next_command_sequence);
if (G_UNLIKELY (rflow != GST_FLOW_OK)) if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
gst_buffer_unmap (buf, data, size);
return rflow; return rflow;
}
/* if no addresses or sizes were given, or if they define an empty SPU, nothing more to do */ /* if no addresses or sizes were given, or if they define an empty SPU, nothing more to do */
if (G_UNLIKELY (ke->spu_right - ke->spu_left < 0 if (G_UNLIKELY (ke->spu_right - ke->spu_left < 0
@ -501,13 +524,16 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
GST_WARNING_OBJECT (ke, "SPU area is empty, nothing to encode"); GST_WARNING_OBJECT (ke, "SPU area is empty, nothing to encode");
kate_bitmap_init (kb); kate_bitmap_init (kb);
kb->width = kb->height = 0; kb->width = kb->height = 0;
gst_buffer_unmap (buf, data, size);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
/* create the palette */ /* create the palette */
rflow = gst_kate_spu_create_spu_palette (ke, kp); rflow = gst_kate_spu_create_spu_palette (ke, kp);
if (G_UNLIKELY (rflow != GST_FLOW_OK)) if (G_UNLIKELY (rflow != GST_FLOW_OK)) {
gst_buffer_unmap (buf, data, size);
return rflow; return rflow;
}
/* create the bitmap */ /* create the bitmap */
kate_bitmap_init (kb); kate_bitmap_init (kb);
@ -517,14 +543,15 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
kb->type = kate_bitmap_type_paletted; kb->type = kate_bitmap_type_paletted;
kb->pixels = (unsigned char *) g_malloc (kb->width * kb->height); kb->pixels = (unsigned char *) g_malloc (kb->width * kb->height);
if (G_UNLIKELY (!kb->pixels)) { if (G_UNLIKELY (!kb->pixels)) {
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Failed to allocate memory for pixel data")); ("Failed to allocate memory for pixel data"));
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
n = 0; n = 0;
pixptr[0] = GST_BUFFER_DATA (buf) + ke->spu_pix_data[0]; pixptr[0] = data + ke->spu_pix_data[0];
pixptr[1] = GST_BUFFER_DATA (buf) + ke->spu_pix_data[1]; pixptr[1] = data + ke->spu_pix_data[1];
nybble_offset[0] = 0; nybble_offset[0] = 0;
nybble_offset[1] = 0; nybble_offset[1] = 0;
max_nybbles[0] = 2 * (packet_size - ke->spu_pix_data[0]); max_nybbles[0] = 2 * (packet_size - ke->spu_pix_data[0]);
@ -591,6 +618,7 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
probably going to end before the next one while being readable */ probably going to end before the next one while being readable */
//ke->hide_time = ke->show_time + (1000 * 90 / 1024); //ke->hide_time = ke->show_time + (1000 * 90 / 1024);
} }
gst_buffer_unmap (buf, data, size);
return GST_FLOW_OK; return GST_FLOW_OK;
} }
@ -856,15 +884,12 @@ gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev)
bytes[3] = first_commands_offset & 0xff; bytes[3] = first_commands_offset & 0xff;
/* Create a buffer with those values */ /* Create a buffer with those values */
buffer = gst_buffer_new (); buffer = gst_buffer_new_wrapped (bytes, nbytes);
if (G_UNLIKELY (!buffer)) { if (G_UNLIKELY (!buffer)) {
GST_WARNING_OBJECT (kd, GST_WARNING_OBJECT (kd,
"Failed to allocate %" G_GSIZE_FORMAT " byte buffer", nbytes); "Failed to allocate %" G_GSIZE_FORMAT " byte buffer", nbytes);
goto error; goto error;
} }
GST_BUFFER_DATA (buffer) = bytes;
GST_BUFFER_MALLOCDATA (buffer) = bytes;
GST_BUFFER_SIZE (buffer) = nbytes;
GST_BUFFER_OFFSET_END (buffer) = GST_SECOND * (ev->end_time); GST_BUFFER_OFFSET_END (buffer) = GST_SECOND * (ev->end_time);
GST_BUFFER_OFFSET (buffer) = GST_SECOND * (ev->start_time); GST_BUFFER_OFFSET (buffer) = GST_SECOND * (ev->start_time);
GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND * (ev->start_time); GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND * (ev->start_time);

View file

@ -97,38 +97,19 @@ static void gst_kate_tag_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static void gst_kate_tag_dispose (GObject * object); static void gst_kate_tag_dispose (GObject * object);
#define gst_kate_tag_parent_class parent_class
#define _do_init(type) \ G_DEFINE_TYPE_WITH_CODE (GstKateTag, gst_kate_tag, GST_TYPE_KATE_PARSE,
G_STMT_START{ \ G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
static const GInterfaceInfo tag_setter_info = { \
NULL, \
NULL, \
NULL \
}; \
g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, \
&tag_setter_info); \
}G_STMT_END
GST_BOILERPLATE_FULL (GstKateTag, gst_kate_tag, GstKateParse,
GST_TYPE_KATE_PARSE, _do_init);
static void
gst_kate_tag_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details_simple (element_class, "Kate stream tagger",
"Formatter/Metadata",
"Retags kate streams", "Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
}
static void static void
gst_kate_tag_class_init (GstKateTagClass * klass) gst_kate_tag_class_init (GstKateTagClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstKateParseClass *gstkateparse_class; GstKateParseClass *gstkateparse_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstkateparse_class = GST_KATE_PARSE_CLASS (klass); gstkateparse_class = GST_KATE_PARSE_CLASS (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_tag_set_property); gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_tag_set_property);
@ -155,12 +136,16 @@ gst_kate_tag_class_init (GstKateTagClass * klass)
"Set the height of the canvas this stream was authored for (0 is unspecified)", "Set the height of the canvas this stream was authored for (0 is unspecified)",
0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_details_simple (gstelement_class, "Kate stream tagger",
"Formatter/Metadata",
"Retags kate streams", "Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>");
gstkateparse_class->parse_packet = gstkateparse_class->parse_packet =
GST_DEBUG_FUNCPTR (gst_kate_tag_parse_packet); GST_DEBUG_FUNCPTR (gst_kate_tag_parse_packet);
} }
static void static void
gst_kate_tag_init (GstKateTag * kt, GstKateTagClass * g_class) gst_kate_tag_init (GstKateTag * kt)
{ {
kt->language = NULL; kt->language = NULL;
kt->category = NULL; kt->category = NULL;
@ -281,44 +266,52 @@ gst_kate_tag_parse_packet (GstKateParse * parse, GstBuffer * buffer)
GstKateTag *kt; GstKateTag *kt;
gchar *encoder = NULL; gchar *encoder = NULL;
GstBuffer *new_buf; GstBuffer *new_buf;
guint8 *data;
gsize size;
kt = GST_KATE_TAG (parse); kt = GST_KATE_TAG (parse);
/* rewrite the language and category */ data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
if (GST_BUFFER_SIZE (buffer) >= 64 && GST_BUFFER_DATA (buffer)[0] == 0x80) {
GstBuffer *new_buffer = gst_buffer_copy (buffer);
/* rewrite the language and category */
if (size >= 64 && data[0] == 0x80) {
GstBuffer *new_buffer;
gst_buffer_unmap (buffer, data, size);
new_buffer = gst_buffer_copy (buffer);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
buffer = new_buffer; buffer = new_buffer;
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READWRITE);
/* language is at offset 32, 16 bytes, zero terminated */ /* language is at offset 32, 16 bytes, zero terminated */
if (kt->language) { if (kt->language) {
strncpy ((char *) GST_BUFFER_DATA (buffer) + 32, kt->language, 15); strncpy ((char *) data + 32, kt->language, 15);
GST_BUFFER_DATA (buffer)[47] = 0; data[47] = 0;
} }
/* category is at offset 48, 16 bytes, zero terminated */ /* category is at offset 48, 16 bytes, zero terminated */
if (kt->category) { if (kt->category) {
strncpy ((char *) GST_BUFFER_DATA (buffer) + 48, kt->category, 15); strncpy ((char *) data + 48, kt->category, 15);
GST_BUFFER_DATA (buffer)[63] = 0; data[63] = 0;
} }
if (kt->original_canvas_width >= 0) { if (kt->original_canvas_width >= 0) {
guint16 v = encode_canvas_size (kt->original_canvas_width); guint16 v = encode_canvas_size (kt->original_canvas_width);
GST_BUFFER_DATA (buffer)[16] = v & 0xff; data[16] = v & 0xff;
GST_BUFFER_DATA (buffer)[17] = (v >> 8) & 0xff; data[17] = (v >> 8) & 0xff;
} }
if (kt->original_canvas_height >= 0) { if (kt->original_canvas_height >= 0) {
guint16 v = encode_canvas_size (kt->original_canvas_height); guint16 v = encode_canvas_size (kt->original_canvas_height);
GST_BUFFER_DATA (buffer)[18] = v & 0xff; data[18] = v & 0xff;
GST_BUFFER_DATA (buffer)[19] = (v >> 8) & 0xff; data[19] = (v >> 8) & 0xff;
} }
} }
/* rewrite the comments packet */ /* rewrite the comments packet */
if (GST_BUFFER_SIZE (buffer) >= 9 && GST_BUFFER_DATA (buffer)[0] == 0x81) { if (size >= 9 && data[0] == 0x81) {
old_tags = old_tags =
gst_tag_list_from_vorbiscomment_buffer (buffer, gst_tag_list_from_vorbiscomment (data, size,
(const guint8 *) "\201kate\0\0\0\0", 9, &encoder); (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (kt)); user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (kt));
gst_buffer_unmap (buffer, data, size);
/* build new tag list */ /* build new tag list */
new_tags = gst_tag_list_merge (user_tags, old_tags, new_tags = gst_tag_list_merge (user_tags, old_tags,
@ -328,16 +321,18 @@ gst_kate_tag_parse_packet (GstKateParse * parse, GstBuffer * buffer)
new_buf = new_buf =
gst_tag_list_to_vorbiscomment_buffer (new_tags, gst_tag_list_to_vorbiscomment_buffer (new_tags,
(const guint8 *) "\201kate\0\0\0\0", 9, encoder); (const guint8 *) "\201kate\0\0\0\0", 9, encoder);
gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS); gst_buffer_copy_into (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS, 0, -1);
gst_tag_list_free (new_tags); gst_tag_list_free (new_tags);
g_free (encoder); g_free (encoder);
gst_buffer_unref (buffer); gst_buffer_unref (buffer);
/* the buffer will have the framing bit used by Vorbis, but we don't use it */ /* the buffer will have the framing bit used by Vorbis, but we don't use it */
--GST_BUFFER_SIZE (new_buf); gst_buffer_resize (new_buf, 0, gst_buffer_get_size (new_buf) - 1);
buffer = new_buf; buffer = new_buf;
} else {
gst_buffer_unmap (buffer, data, size);
} }
return GST_KATE_PARSE_CLASS (parent_class)->parse_packet (parse, buffer); return GST_KATE_PARSE_CLASS (parent_class)->parse_packet (parse, buffer);

View file

@ -247,12 +247,16 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
int ret; int ret;
GstFlowReturn rflow = GST_FLOW_OK; GstFlowReturn rflow = GST_FLOW_OK;
gboolean is_header; gboolean is_header;
guint8 *data;
gsize size;
guint8 header[1];
size = gst_buffer_extract (buf, 0, header, 1);
GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x", GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
GST_BUFFER_SIZE (buf), gst_buffer_get_size (buf), size == 0 ? -1 : header[0]);
GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80); is_header = size > 0 && (header[0] & 0x80);
if (!is_header && decoder->tags) { if (!is_header && decoder->tags) {
/* after we've processed headers, send any tags before processing the data packet */ /* after we've processed headers, send any tags before processing the data packet */
@ -262,8 +266,11 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
decoder->tags = NULL; decoder->tags = NULL;
} }
kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf)); data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
kate_packet_wrap (&kp, size, data);
ret = kate_high_decode_packetin (&decoder->k, &kp, ev); ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
gst_buffer_unmap (buf, data, size);
if (G_UNLIKELY (ret < 0)) { if (G_UNLIKELY (ret < 0)) {
GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
("Failed to decode Kate packet: %d", ret)); ("Failed to decode Kate packet: %d", ret));
@ -277,7 +284,7 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
/* headers may be interesting to retrieve information from */ /* headers may be interesting to retrieve information from */
if (G_UNLIKELY (is_header)) { if (G_UNLIKELY (is_header)) {
switch (GST_BUFFER_DATA (buf)[0]) { switch (header[0]) {
case 0x80: /* ID header */ case 0x80: /* ID header */
GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s", GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
decoder->k.ki->language, decoder->k.ki->category); decoder->k.ki->language, decoder->k.ki->category);
@ -484,37 +491,23 @@ gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
} }
void void
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder,
GstEvent * event) GstEvent * event)
{ {
gboolean update; GstSegment seg;
gdouble rate;
GstFormat format;
gint64 start, stop, time;
gdouble arate;
gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, gst_event_copy_segment (event, &seg);
&start, &stop, &time);
GST_DEBUG_OBJECT (decoder, "kate pad segment:" GST_DEBUG_OBJECT (decoder, "kate pad segment: %" GST_SEGMENT_FORMAT, &seg);
" Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT
" %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, decoder->kate_segment = seg;
update, rate, arate, format, GST_TIME_ARGS (start),
GST_TIME_ARGS (stop), GST_TIME_ARGS (time));
if (!update) {
/* Tiger uses this segment is used to remap the video running time to the
Kate running time. The sending of segment updates to keep streams in sync
does kinda rain on our parade though, and since we don't need these,
we just ignore those here */
gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate,
arate, format, start, stop, time);
}
} }
gboolean gboolean
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
GstElement * element, GstBuffer * buf) GstElement * element, GstBuffer * buf)
{ {
gint64 clip_start = 0, clip_stop = 0; guint64 clip_start = 0, clip_stop = 0;
gboolean in_seg; gboolean in_seg;
if (decoder->kate_flushing) { if (decoder->kate_flushing) {
@ -538,8 +531,7 @@ gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
if (in_seg) { if (in_seg) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME, decoder->kate_segment.position = clip_start;
clip_start);
} }
} else { } else {
GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored"); GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored");

View file

@ -82,7 +82,7 @@ extern void
gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder, gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
gboolean flushing); gboolean flushing);
extern void extern void
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder,
GstEvent * event); GstEvent * event);
extern gboolean extern gboolean
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,