#include "gstdvdsubparse.h"
#include <string.h>
-GST_BOILERPLATE (GstDvdSubDec, gst_dvd_sub_dec, GstElement, GST_TYPE_ELEMENT);
+#define gst_dvd_sub_dec_parent_class parent_class
+G_DEFINE_TYPE (GstDvdSubDec, gst_dvd_sub_dec, GST_TYPE_ELEMENT);
static gboolean gst_dvd_sub_dec_src_event (GstPad * srcpad, GstEvent * event);
static GstFlowReturn gst_dvd_sub_dec_chain (GstPad * pad, GstBuffer * buf);
GstEvent * event);
static void gst_dvd_sub_dec_finalize (GObject * gobject);
static void gst_setup_palette (GstDvdSubDec * dec);
-static void gst_dvd_sub_dec_merge_title (GstDvdSubDec * dec, GstBuffer * buf);
+static void gst_dvd_sub_dec_merge_title (GstDvdSubDec * dec,
+ GstVideoFrame * frame);
static GstClockTime gst_dvd_sub_dec_get_event_delay (GstDvdSubDec * dec);
static gboolean gst_dvd_sub_dec_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_dvd_sub_dec_sink_setcaps (GstPad * pad, GstCaps * caps);
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-raw-yuv, format = (fourcc) AYUV, "
- "width = (int) 720, height = (int) 576, framerate = (fraction) 0/1; "
- "video/x-raw-rgb, "
- "width = (int) 720, height = (int) 576, framerate = (fraction) 0/1, "
- "bpp = (int) 32, endianness = (int) 4321, red_mask = (int) 16711680, "
- "green_mask = (int) 65280, blue_mask = (int) 255, "
- " alpha_mask = (int) -16777216, depth = (int) 32")
+ GST_STATIC_CAPS ("video/x-raw, format = (string) { AYUV, ARGB },"
+ "width = (int) 720, height = (int) 576, framerate = (fraction) 0/1")
);
static GstStaticPadTemplate subtitle_template = GST_STATIC_PAD_TEMPLATE ("sink",
RLE_state;
static void
-gst_dvd_sub_dec_base_init (gpointer klass)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&src_template));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&subtitle_template));
-
- gst_element_class_set_details_simple (element_class, "DVD subtitle decoder",
- "Codec/Decoder/Video", "Decodes DVD subtitles into AYUV video frames",
- "Wim Taymans <wim.taymans@gmail.com>, "
- "Jan Schmidt <thaytan@mad.scientist.com>");
-}
-
-static void
gst_dvd_sub_dec_class_init (GstDvdSubDecClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
gobject_class = (GObjectClass *) klass;
+ gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = gst_dvd_sub_dec_finalize;
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&src_template));
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&subtitle_template));
+
+ gst_element_class_set_details_simple (gstelement_class,
+ "DVD subtitle decoder", "Codec/Decoder/Video",
+ "Decodes DVD subtitles into AYUV video frames",
+ "Wim Taymans <wim.taymans@gmail.com>, "
+ "Jan Schmidt <thaytan@mad.scientist.com>");
}
static void
-gst_dvd_sub_dec_init (GstDvdSubDec * dec, GstDvdSubDecClass * klass)
+gst_dvd_sub_dec_init (GstDvdSubDec * dec)
{
GstPadTemplate *tmpl;
gst_pad_set_event_function (dec->sinkpad,
GST_DEBUG_FUNCPTR (gst_dvd_sub_dec_sink_event));
gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad);
- gst_pad_set_setcaps_function (dec->sinkpad, gst_dvd_sub_dec_sink_setcaps);
tmpl = gst_static_pad_template_get (&src_template);
dec->srcpad = gst_pad_new_from_template (tmpl, "src");
dec->in_height = 576;
dec->partialbuf = NULL;
+ dec->partialdata = NULL;
dec->have_title = FALSE;
dec->parse_pos = NULL;
dec->forced_display = FALSE;
GstDvdSubDec *dec = GST_DVD_SUB_DEC (gobject);
if (dec->partialbuf) {
+ gst_buffer_unmap (dec->partialbuf, dec->partialdata, dec->partialsize);
gst_buffer_unref (dec->partialbuf);
dec->partialbuf = NULL;
}
static GstClockTime
gst_dvd_sub_dec_get_event_delay (GstDvdSubDec * dec)
{
- guchar *start = GST_BUFFER_DATA (dec->partialbuf);
guchar *buf;
guint16 ticks;
GstClockTime event_delay;
/* If starting a new buffer, follow the first DCSQ ptr */
- if (dec->parse_pos == start) {
+ if (dec->parse_pos == dec->partialdata) {
buf = dec->parse_pos + dec->data_size;
} else {
buf = dec->parse_pos;
{ GST_WARNING("Subtitle stream broken parsing %c", *buf); \
broken = TRUE; break; }
- guchar *start = GST_BUFFER_DATA (dec->partialbuf);
+ guchar *start = dec->partialdata;
guchar *buf;
guchar *end;
gboolean broken = FALSE;
* frame buffer.
*/
static void
-gst_dvd_sub_dec_merge_title (GstDvdSubDec * dec, GstBuffer * buf)
+gst_dvd_sub_dec_merge_title (GstDvdSubDec * dec, GstVideoFrame * frame)
{
gint y;
- gint Y_stride = 4 * dec->in_width;
- guchar *buffer = GST_BUFFER_DATA (dec->partialbuf);
-
+ gint Y_stride;
+ guchar *buffer = dec->partialdata;
gint hl_top, hl_bottom;
gint last_y;
RLE_state state;
+ guint8 *Y_data;;
- GST_DEBUG_OBJECT (dec, "Merging subtitle on frame at time %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
+ GST_DEBUG_OBJECT (dec, "Merging subtitle on frame");
+
+ Y_data = GST_VIDEO_FRAME_PLANE_DATA (frame, 0);
+ Y_stride = GST_VIDEO_FRAME_PLANE_STRIDE (frame, 0);
state.id = 0;
state.aligned = 1;
last_y = MIN (dec->bottom, dec->in_height);
y = dec->top;
- state.target = GST_BUFFER_DATA (buf) + 4 * dec->left + (y * Y_stride);
+ state.target = Y_data + 4 * dec->left + (y * Y_stride);
/* Now draw scanlines until we hit last_y or end of RLE data */
for (; ((state.offset[1] < dec->data_size + 2) && (y <= last_y)); y++) {
gst_send_empty_fill (GstDvdSubDec * dec, GstClockTime ts)
{
if (dec->next_ts < ts) {
+ GstSegment seg;
+
GST_LOG_OBJECT (dec, "Sending newsegment update to advance time to %"
GST_TIME_FORMAT, GST_TIME_ARGS (ts));
- gst_pad_push_event (dec->srcpad,
- gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, ts, -1, ts));
+ gst_segment_init (&seg, GST_FORMAT_TIME);
+ seg.start = ts;
+ seg.time = ts;
+
+ gst_pad_push_event (dec->srcpad, gst_event_new_segment (&seg));
}
dec->next_ts = ts;
}
{
GstFlowReturn flow;
GstBuffer *out_buf;
+ GstVideoFrame frame;
+ guint8 *data;
gint x, y;
g_assert (dec->have_title);
goto out;
}
- flow = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, 0,
- 4 * dec->in_width * dec->in_height, GST_PAD_CAPS (dec->srcpad), &out_buf);
+ out_buf =
+ gst_buffer_new_allocate (NULL, 4 * GST_VIDEO_INFO_SIZE (&dec->info), 3);
+ gst_video_frame_map (&frame, &dec->info, out_buf, GST_MAP_READWRITE);
- if (flow != GST_FLOW_OK) {
- GST_DEBUG_OBJECT (dec, "alloc buffer failed: flow = %s",
- gst_flow_get_name (flow));
- goto out;
- }
+ data = GST_VIDEO_FRAME_PLANE_DATA (&frame, 0);
/* Clear the buffer */
/* FIXME - move this into the buffer rendering code */
for (y = 0; y < dec->in_height; y++) {
- guchar *line = GST_BUFFER_DATA (out_buf) + 4 * dec->in_width * y;
+ guchar *line = data + 4 * dec->in_width * y;
for (x = 0; x < dec->in_width; x++) {
line[0] = 0; /* A */
/* FIXME: do we really want to honour the forced_display flag
* for subtitles streans? */
if (dec->visible || dec->forced_display) {
- gst_dvd_sub_dec_merge_title (dec, out_buf);
+ gst_dvd_sub_dec_merge_title (dec, &frame);
}
+ gst_video_frame_unmap (&frame);
+
dec->buf_dirty = FALSE;
GST_BUFFER_TIMESTAMP (out_buf) = dec->next_ts;
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out_buf)),
GST_BUFFER_DURATION (out_buf));
- gst_buffer_set_caps (out_buf, GST_PAD_CAPS (dec->srcpad));
-
flow = gst_pad_push (dec->srcpad, out_buf);
out:
dec = GST_DVD_SUB_DEC (GST_PAD_PARENT (pad));
GST_DEBUG_OBJECT (dec, "Have buffer of size %d, ts %"
- GST_TIME_FORMAT ", dur %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buf),
+ GST_TIME_FORMAT ", dur %" G_GINT64_FORMAT, gst_buffer_get_size (buf),
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_DURATION (buf));
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
}
if (dec->have_title) {
+ gst_buffer_unmap (dec->partialbuf, dec->partialdata, dec->partialsize);
gst_buffer_unref (dec->partialbuf);
dec->partialbuf = NULL;
dec->have_title = FALSE;
if (dec->partialbuf) {
GstBuffer *merge;
+ gst_buffer_unmap (dec->partialbuf, dec->partialdata, dec->partialsize);
merge = gst_buffer_join (dec->partialbuf, buf);
dec->partialbuf = merge;
} else {
dec->partialbuf = buf;
}
- data = GST_BUFFER_DATA (dec->partialbuf);
- size = GST_BUFFER_SIZE (dec->partialbuf);
+ dec->partialdata =
+ gst_buffer_map (dec->partialbuf, &dec->partialsize, NULL, GST_MAP_READ);
+
+ data = dec->partialdata;
+ size = dec->partialsize;
if (size > 4) {
dec->packet_size = GST_READ_UINT16_BE (data);
{
GstDvdSubDec *dec = GST_DVD_SUB_DEC (gst_pad_get_parent (pad));
gboolean ret = FALSE;
- guint32 fourcc = GST_MAKE_FOURCC ('A', 'Y', 'U', 'V');
GstCaps *out_caps = NULL, *peer_caps = NULL;
GST_DEBUG_OBJECT (dec, "setcaps called with %" GST_PTR_FORMAT, caps);
- dec->out_fourcc = fourcc;
- out_caps = gst_caps_new_simple ("video/x-raw-yuv",
+ out_caps = gst_caps_new_simple ("video/x-raw",
+ "format", G_TYPE_STRING, "AYUV",
"width", G_TYPE_INT, dec->in_width,
"height", G_TYPE_INT, dec->in_height,
- "format", GST_TYPE_FOURCC, dec->out_fourcc,
"framerate", GST_TYPE_FRACTION, 0, 1, NULL);
peer_caps = gst_pad_get_allowed_caps (dec->srcpad);
if (G_LIKELY (peer_caps)) {
guint i = 0, n = 0;
+
n = gst_caps_get_size (peer_caps);
GST_DEBUG_OBJECT (dec, "peer allowed caps (%u structure(s)) are %"
GST_PTR_FORMAT, n, peer_caps);
for (i = 0; i < n; i++) {
GstStructure *s = gst_caps_get_structure (peer_caps, i);
/* Check if the peer pad support ARGB format, if yes change caps */
- if (gst_structure_has_name (s, "video/x-raw-rgb") &&
- gst_structure_has_field (s, "alpha_mask")) {
+ if (gst_structure_has_name (s, "video/x-raw")) {
gst_caps_unref (out_caps);
- GST_DEBUG_OBJECT (dec, "trying with fourcc %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
- out_caps = gst_caps_new_simple ("video/x-raw-rgb",
+ GST_DEBUG_OBJECT (dec, "trying with ARGB");
+
+ out_caps = gst_caps_new_simple ("video/x-raw",
+ "format", G_TYPE_STRING, "ARGB",
"width", G_TYPE_INT, dec->in_width,
"height", G_TYPE_INT, dec->in_height,
- "framerate", GST_TYPE_FRACTION, 0, 1,
- "bpp", G_TYPE_INT, 32,
- "depth", G_TYPE_INT, 32,
- "red_mask", G_TYPE_INT, 16711680,
- "green_mask", G_TYPE_INT, 65280,
- "blue_mask", G_TYPE_INT, 255,
- "alpha_mask", G_TYPE_INT, -16777216,
- "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
+ "framerate", GST_TYPE_FRACTION, 0, 1, NULL);
+
if (gst_pad_peer_accept_caps (dec->srcpad, out_caps)) {
- GST_DEBUG_OBJECT (dec, "peer accepted format %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (fourcc));
+ GST_DEBUG_OBJECT (dec, "peer accepted ARGB");
/* If ARGB format then set the flag */
dec->use_ARGB = TRUE;
break;
GST_DEBUG_OBJECT (dec, "setting caps downstream to %" GST_PTR_FORMAT,
out_caps);
if (gst_pad_set_caps (dec->srcpad, out_caps)) {
- dec->out_fourcc = fourcc;
+ gst_video_info_from_caps (&dec->info, out_caps);
} else {
GST_WARNING_OBJECT (dec, "failed setting downstream caps");
gst_caps_unref (out_caps);
GST_LOG_OBJECT (dec, "%s event", GST_EVENT_TYPE_NAME (event));
switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_CAPS:
+ {
+ GstCaps *caps;
+
+ gst_event_parse_caps (event, &caps);
+ ret = gst_dvd_sub_dec_sink_setcaps (pad, caps);
+ gst_event_unref (event);
+ break;
+ }
case GST_EVENT_CUSTOM_DOWNSTREAM:{
GstClockTime ts = GST_EVENT_TIMESTAMP (event);
- if (event->structure != NULL &&
- gst_structure_has_name (event->structure, "application/x-gst-dvd")) {
-
+ if (gst_event_has_name (event, "application/x-gst-dvd")) {
if (GST_CLOCK_TIME_IS_VALID (ts))
gst_dvd_sub_dec_advance_time (dec, ts);
ret = gst_pad_event_default (pad, event);
break;
}
- case GST_EVENT_NEWSEGMENT:{
- gboolean update;
- GstFormat format;
- gint64 start, stop, pos;
+ case GST_EVENT_SEGMENT:
+ {
+ GstSegment seg;
- gst_event_parse_new_segment (event, &update, NULL, &format, &start,
- &stop, &pos);
+ gst_event_copy_segment (event, &seg);
+#if 0
if (update) {
/* update ... advance time */
if (GST_CLOCK_TIME_IS_VALID (pos)) {
}
gst_event_unref (event);
ret = TRUE;
- } else {
+ } else
+#endif
+ {
/* not just an update ... */
/* Turn off forced highlight display */
// dec->forced_display = 0;
// dec->current_button = 0;
if (dec->partialbuf) {
+ gst_buffer_unmap (dec->partialbuf, dec->partialdata,
+ dec->partialsize);
gst_buffer_unref (dec->partialbuf);
dec->partialbuf = NULL;
dec->have_title = FALSE;
}
- if (GST_CLOCK_TIME_IS_VALID (pos))
- dec->next_ts = pos;
+ if (GST_CLOCK_TIME_IS_VALID (seg.time))
+ dec->next_ts = seg.time;
else
dec->next_ts = GST_CLOCK_TIME_NONE;
dec->current_button = 0;
if (dec->partialbuf) {
+ gst_buffer_unmap (dec->partialbuf, dec->partialdata, dec->partialsize);
gst_buffer_unref (dec->partialbuf);
dec->partialbuf = NULL;
dec->have_title = FALSE;