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_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,
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_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)
{
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>");
}
static GstCaps *gst_kate_dec_src_get_caps (GstPad * pad, GstCaps * filter);
/* initialize the plugin's class */
static void
@ -170,6 +155,16 @@ gst_kate_dec_class_init (GstKateDecClass * klass)
gstelement_class->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
@ -178,7 +173,7 @@ gst_kate_dec_class_init (GstKateDecClass * klass)
* initialize structure
*/
static void
gst_kate_dec_init (GstKateDec * dec, GstKateDecClass * gclass)
gst_kate_dec_init (GstKateDec * dec)
{
GST_DEBUG_OBJECT (dec, "gst_kate_dec_init");
@ -295,11 +290,10 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf)
if (G_LIKELY (buffer)) {
const char *mime = plain ? "text/plain" : "text/x-pango-markup";
GstCaps *caps = gst_caps_new_simple (mime, NULL);
gst_buffer_set_caps (buffer, caps);
gst_caps_unref (caps);
/* allocate and copy the NULs, but don't include them in passed size */
memcpy (GST_BUFFER_DATA (buffer), escaped, len + 1);
GST_BUFFER_SIZE (buffer) = len;
gst_buffer_fill (buffer, 0, escaped, len + 1);
gst_buffer_resize (buffer, 0, len);
GST_BUFFER_TIMESTAMP (buffer) = ev->start_time * GST_SECOND;
GST_BUFFER_DURATION (buffer) =
(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) {
GstBuffer *buffer = gst_kate_spu_encode_spu (kd, ev);
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_DURATION (buffer) =
(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));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_NEWSEGMENT:
gst_kate_util_decoder_base_new_segment_event (&kd->decoder, event);
case GST_EVENT_SEGMENT:
gst_kate_util_decoder_base_segment_event (&kd->decoder, event);
res = gst_pad_event_default (pad, event);
break;
@ -442,7 +433,7 @@ gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event)
}
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)));
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 const GstQueryType *gst_kate_enc_source_query_type (GstPad * pad);
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,
GST_TYPE_ELEMENT, gst_kate_enc_add_interfaces);
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>");
}
#define gst_kate_enc_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstKateEnc, gst_kate_enc, GST_TYPE_ELEMENT,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
/* initialize the plugin's class */
static void
@ -173,8 +157,6 @@ gst_kate_enc_class_init (GstKateEncClass * klass)
gobject_class = (GObjectClass *) 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->get_property = GST_DEBUG_FUNCPTR (gst_kate_enc_get_property);
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 =
GST_DEBUG_FUNCPTR (gst_kate_enc_change_state);
}
static void
gst_kate_enc_add_interfaces (GType kateenc_type)
{
static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL };
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));
g_type_add_interface_static (kateenc_type, GST_TYPE_TAG_SETTER,
&tag_setter_info);
gst_element_class_set_details_simple (gstelement_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 new element
@ -245,7 +228,7 @@ gst_kate_enc_add_interfaces (GType kateenc_type)
* initialize structure
*/
static void
gst_kate_enc_init (GstKateEnc * ke, GstKateEncClass * gclass)
gst_kate_enc_init (GstKateEnc * ke)
{
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_pad_set_event_function (ke->sinkpad,
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);
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->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)) {
GST_WARNING_OBJECT (ke, "Failed to allocate buffer for %u bytes",
(guint) kp->nbytes);
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:
OFFSET_END is the granulepos
@ -644,16 +625,6 @@ gst_kate_enc_send_headers (GstKateEnc * ke)
if (caps) {
GST_DEBUG_OBJECT (ke, "here are the caps: %" GST_PTR_FORMAT, 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_LOG_OBJECT (ke, "pushing headers");
@ -869,7 +840,7 @@ gst_kate_enc_chain_spu (GstKateEnc * ke, GstBuffer * buf)
#endif
GST_DEBUG_OBJECT (ke, "Encoding %ux%u SPU: (%u bytes) from %f to %f",
(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);
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));
rflow = GST_FLOW_ERROR;
} 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) {
size_t text_len = GST_BUFFER_SIZE (buf);
kate_float t0 = start / (double) GST_SECOND;
kate_float t1 = stop / (double) GST_SECOND;
GST_LOG_OBJECT (ke, "Encoding text: %*.*s (%u bytes) from %f to %f",
(int) text_len, (int) text_len, GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf), t0, t1);
(int) text_len, (int) text_len, text, text_len, t0, t1);
ret = kate_encode_text (&ke->k, t0, t1, text, text_len, &kp);
if (G_UNLIKELY (ret < 0)) {
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Failed to encode text: %d", ret));
@ -976,6 +950,7 @@ gst_kate_enc_chain_text (GstKateEnc * ke, GstBuffer * buf,
("no text in text packet"));
rflow = GST_FLOW_ERROR;
}
gst_buffer_unmap (buf, text, text_len);
}
return rflow;
@ -992,10 +967,10 @@ gst_kate_enc_chain (GstPad * pad, GstBuffer * buf)
GstCaps *caps;
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 */
caps = GST_PAD_CAPS (pad);
caps = gst_pad_get_current_caps (pad);
if (G_UNLIKELY (caps == NULL)) {
GST_WARNING_OBJECT (ke, "No input caps set");
rflow = GST_FLOW_NOT_NEGOTIATED;
@ -1027,6 +1002,7 @@ gst_kate_enc_chain (GstPad * pad, GstBuffer * buf)
} else {
GST_WARNING_OBJECT (ke, "Packet has no MIME type, ignored");
}
gst_caps_unref (caps);
}
gst_buffer_unref (buf);
@ -1261,38 +1237,46 @@ static gboolean
gst_kate_enc_sink_event (GstPad * pad, GstEvent * event)
{
GstKateEnc *ke = GST_KATE_ENC (gst_pad_get_parent (pad));
GstStructure *structure;
const GstStructure *structure;
gboolean ret;
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");
if (ke->initialized) {
GST_LOG_OBJECT (ke, "ensuring all headers are in");
if (gst_kate_enc_flush_headers (ke) != GST_FLOW_OK) {
GST_WARNING_OBJECT (ke, "Failed to flush headers");
} else {
GstFormat format;
gint64 timestamp;
GstSegment seg;
gst_event_parse_new_segment (event, NULL, NULL, &format, &timestamp,
NULL, NULL);
if (format != GST_FORMAT_TIME || !GST_CLOCK_TIME_IS_VALID (timestamp)) {
gst_event_copy_segment (event, &seg);
if (seg.format != GST_FORMAT_TIME
|| !GST_CLOCK_TIME_IS_VALID (seg.start)) {
GST_WARNING_OBJECT (ke,
"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
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
run the risk of stalling the pipeline and hanging, which is Very Bad. Oh dear. We can't exit(-1), can we ? */
} else {
float t = timestamp / (double) GST_SECOND;
float t = seg.start / (double) GST_SECOND;
if (ke->delayed_spu
&& t - ke->delayed_start / (double) GST_SECOND >=
ke->default_spu_duration) {
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");
/* 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
mean out of sequence start times - and granulepos */
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:
GST_LOG_OBJECT (ke, "Got custom downstream event");
/* adapted from the dvdsubdec element */
structure = event->structure;
structure = gst_event_get_structure (event);
if (structure != NULL
&& gst_structure_has_name (structure, "application/x-gst-dvd")) {
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_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 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,
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
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;
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);
}
static void
gst_kate_parse_init (GstKateParse * parse, GstKateParseClass * g_class)
gst_kate_parse_init (GstKateParse * parse)
{
parse->sinkpad =
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 */
caps =
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)) {
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL),
@ -184,13 +180,18 @@ gst_kate_parse_push_headers (GstKateParse * parse)
headers = parse->streamheader;
while (headers) {
guint8 *data;
gsize size;
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);
if (G_UNLIKELY (ret < 0)) {
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 */
outbuf_list = g_list_append (outbuf_list, outbuf);
headers = headers->next;
@ -203,7 +204,6 @@ gst_kate_parse_push_headers (GstKateParse * parse)
headers = outbuf_list;
while (headers) {
outbuf = GST_BUFFER_CAST (headers->data);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (parse->srcpad));
gst_pad_push (parse->srcpad, outbuf);
headers = headers->next;
}
@ -255,8 +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);
gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad));
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;
gint64 granpos;
buf = gst_buffer_make_metadata_writable (buf);
buf = gst_buffer_make_writable (buf);
/* oggdemux stores the granule pos in the offset end */
granpos = GST_BUFFER_OFFSET_END (buf);
@ -347,17 +345,20 @@ static GstFlowReturn
gst_kate_parse_parse_packet (GstKateParse * parse, GstBuffer * buf)
{
GstFlowReturn ret = GST_FLOW_OK;
guint8 header[1];
gsize size;
g_assert (parse);
parse->packetno++;
GST_LOG_OBJECT (parse, "Got packet %02x, %u bytes",
GST_BUFFER_SIZE (buf) ? GST_BUFFER_DATA (buf)[0] : -1,
GST_BUFFER_SIZE (buf));
size = gst_buffer_extract (buf, 0, header, 1);
if (GST_BUFFER_SIZE (buf) > 0 && GST_BUFFER_DATA (buf)[0] & 0x80) {
GST_DEBUG_OBJECT (parse, "Found header %02x", GST_BUFFER_DATA (buf)[0]);
GST_LOG_OBJECT (parse, "Got packet %02x, %u bytes",
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,
* so put it on the streamheader list and return */
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);
if (G_UNLIKELY (GST_PAD_CAPS (pad) == NULL))
if (G_UNLIKELY (!gst_pad_has_current_caps (pad)))
return GST_FLOW_NOT_NEGOTIATED;
return klass->parse_packet (parse, buffer);
@ -602,7 +603,7 @@ gst_kate_parse_change_state (GstElement * element, GstStateChange transition)
break;
}
ret = parent_class->change_state (element, transition);
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
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 next_command_sequence;
const guint8 *ptr;
guint8 *data;
guint16 sz;
gsize size;
if (command_sequence_offset >= GST_BUFFER_SIZE (buf)) {
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;
}
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
ptr = GST_BUFFER_DATA (buf) + command_sequence_offset;
sz = GST_BUFFER_SIZE (buf) - command_sequence_offset;
if (command_sequence_offset >= size)
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)",
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) {
GST_DEBUG_OBJECT (ke, "Jumping to next sequence at offset %u",
next_command_sequence);
gst_buffer_unmap (buf, data, size);
return gst_kate_spu_decode_command_sequence (ke, buf,
next_command_sequence);
} else {
gst_buffer_unmap (buf, data, size);
GST_DEBUG_OBJECT (ke, "No more sequences to decode");
return GST_FLOW_OK;
}
break;
default:
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Invalid SPU command: %u", cmd));
return GST_FLOW_ERROR;
}
}
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL), ("Error parsing SPU"));
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
@ -451,8 +465,10 @@ GstFlowReturn
gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
kate_bitmap * kb, kate_palette * kp)
{
const guint8 *ptr = GST_BUFFER_DATA (buf);
size_t sz = GST_BUFFER_SIZE (buf);
guint8 *data;
gsize size;
const guint8 *ptr;
size_t sz;
guint16 packet_size;
guint16 x, y;
size_t n;
@ -463,6 +479,11 @@ gst_kate_spu_decode_spu (GstKateEnc * ke, GstBuffer * buf, kate_region * kr,
guint16 next_command_sequence;
guint16 code;
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
ptr = data;
sz = size;
/* before decoding anything, initialize to sensible defaults */
memset (ke->spu_colormap, 0, sizeof (ke->spu_colormap));
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);
ADVANCE (2);
GST_DEBUG_OBJECT (ke, "packet size %u (GstBuffer size %u)", packet_size,
GST_BUFFER_SIZE (buf));
size);
CHECK (2);
next_command_sequence = GST_KATE_UINT16_BE (ptr);
ADVANCE (2);
ptr = GST_BUFFER_DATA (buf) + next_command_sequence;
sz = GST_BUFFER_SIZE (buf) - next_command_sequence;
ptr = data + next_command_sequence;
sz = size - next_command_sequence;
GST_DEBUG_OBJECT (ke, "next command sequence at %u for %u",
next_command_sequence, (guint) sz);
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;
}
/* 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
@ -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");
kate_bitmap_init (kb);
kb->width = kb->height = 0;
gst_buffer_unmap (buf, data, size);
return GST_FLOW_OK;
}
/* create the palette */
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;
}
/* create the bitmap */
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->pixels = (unsigned char *) g_malloc (kb->width * kb->height);
if (G_UNLIKELY (!kb->pixels)) {
gst_buffer_unmap (buf, data, size);
GST_ELEMENT_ERROR (ke, STREAM, ENCODE, (NULL),
("Failed to allocate memory for pixel data"));
return GST_FLOW_ERROR;
}
n = 0;
pixptr[0] = GST_BUFFER_DATA (buf) + ke->spu_pix_data[0];
pixptr[1] = GST_BUFFER_DATA (buf) + ke->spu_pix_data[1];
pixptr[0] = data + ke->spu_pix_data[0];
pixptr[1] = data + ke->spu_pix_data[1];
nybble_offset[0] = 0;
nybble_offset[1] = 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 */
//ke->hide_time = ke->show_time + (1000 * 90 / 1024);
}
gst_buffer_unmap (buf, data, size);
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;
/* Create a buffer with those values */
buffer = gst_buffer_new ();
buffer = gst_buffer_new_wrapped (bytes, nbytes);
if (G_UNLIKELY (!buffer)) {
GST_WARNING_OBJECT (kd,
"Failed to allocate %" G_GSIZE_FORMAT " byte buffer", nbytes);
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 (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);
static void gst_kate_tag_dispose (GObject * object);
#define _do_init(type) \
G_STMT_START{ \
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>");
}
#define gst_kate_tag_parent_class parent_class
G_DEFINE_TYPE_WITH_CODE (GstKateTag, gst_kate_tag, GST_TYPE_KATE_PARSE,
G_IMPLEMENT_INTERFACE (GST_TYPE_TAG_SETTER, NULL));
static void
gst_kate_tag_class_init (GstKateTagClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstKateParseClass *gstkateparse_class;
gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
gstkateparse_class = GST_KATE_PARSE_CLASS (klass);
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)",
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 =
GST_DEBUG_FUNCPTR (gst_kate_tag_parse_packet);
}
static void
gst_kate_tag_init (GstKateTag * kt, GstKateTagClass * g_class)
gst_kate_tag_init (GstKateTag * kt)
{
kt->language = NULL;
kt->category = NULL;
@ -281,44 +266,52 @@ gst_kate_tag_parse_packet (GstKateParse * parse, GstBuffer * buffer)
GstKateTag *kt;
gchar *encoder = NULL;
GstBuffer *new_buf;
guint8 *data;
gsize size;
kt = GST_KATE_TAG (parse);
/* rewrite the language and category */
if (GST_BUFFER_SIZE (buffer) >= 64 && GST_BUFFER_DATA (buffer)[0] == 0x80) {
GstBuffer *new_buffer = gst_buffer_copy (buffer);
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
/* 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);
buffer = new_buffer;
data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READWRITE);
/* language is at offset 32, 16 bytes, zero terminated */
if (kt->language) {
strncpy ((char *) GST_BUFFER_DATA (buffer) + 32, kt->language, 15);
GST_BUFFER_DATA (buffer)[47] = 0;
strncpy ((char *) data + 32, kt->language, 15);
data[47] = 0;
}
/* category is at offset 48, 16 bytes, zero terminated */
if (kt->category) {
strncpy ((char *) GST_BUFFER_DATA (buffer) + 48, kt->category, 15);
GST_BUFFER_DATA (buffer)[63] = 0;
strncpy ((char *) data + 48, kt->category, 15);
data[63] = 0;
}
if (kt->original_canvas_width >= 0) {
guint16 v = encode_canvas_size (kt->original_canvas_width);
GST_BUFFER_DATA (buffer)[16] = v & 0xff;
GST_BUFFER_DATA (buffer)[17] = (v >> 8) & 0xff;
data[16] = v & 0xff;
data[17] = (v >> 8) & 0xff;
}
if (kt->original_canvas_height >= 0) {
guint16 v = encode_canvas_size (kt->original_canvas_height);
GST_BUFFER_DATA (buffer)[18] = v & 0xff;
GST_BUFFER_DATA (buffer)[19] = (v >> 8) & 0xff;
data[18] = v & 0xff;
data[19] = (v >> 8) & 0xff;
}
}
/* rewrite the comments packet */
if (GST_BUFFER_SIZE (buffer) >= 9 && GST_BUFFER_DATA (buffer)[0] == 0x81) {
if (size >= 9 && data[0] == 0x81) {
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);
user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (kt));
gst_buffer_unmap (buffer, data, size);
/* build new tag list */
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 =
gst_tag_list_to_vorbiscomment_buffer (new_tags,
(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);
g_free (encoder);
gst_buffer_unref (buffer);
/* 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;
} else {
gst_buffer_unmap (buffer, data, size);
}
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;
GstFlowReturn rflow = GST_FLOW_OK;
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_BUFFER_SIZE (buf),
GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
gst_buffer_get_size (buf), size == 0 ? -1 : header[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) {
/* 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;
}
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);
gst_buffer_unmap (buf, data, size);
if (G_UNLIKELY (ret < 0)) {
GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
("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 */
if (G_UNLIKELY (is_header)) {
switch (GST_BUFFER_DATA (buf)[0]) {
switch (header[0]) {
case 0x80: /* ID header */
GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
decoder->k.ki->language, decoder->k.ki->category);
@ -484,37 +491,23 @@ gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder,
}
void
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder,
GstEvent * event)
{
gboolean update;
gdouble rate;
GstFormat format;
gint64 start, stop, time;
gdouble arate;
GstSegment seg;
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));
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);
}
gst_event_copy_segment (event, &seg);
GST_DEBUG_OBJECT (decoder, "kate pad segment: %" GST_SEGMENT_FORMAT, &seg);
decoder->kate_segment = seg;
}
gboolean
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
GstElement * element, GstBuffer * buf)
{
gint64 clip_start = 0, clip_stop = 0;
guint64 clip_start = 0, clip_stop = 0;
gboolean in_seg;
if (decoder->kate_flushing) {
@ -538,8 +531,7 @@ gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,
if (in_seg) {
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME,
clip_start);
decoder->kate_segment.position = clip_start;
}
} else {
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,
gboolean flushing);
extern void
gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder,
gst_kate_util_decoder_base_segment_event (GstKateDecoderBase * decoder,
GstEvent * event);
extern gboolean
gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder,