-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
-/*
- * libdvbsub - DVB subtitle decoding
+/* dvb-sub.c - DVB subtitle decoding
* Copyright (C) Mart Raudsepp 2009 <mart.raudsepp@artecdesign.ee>
+ * Copyright (C) 2010 ONELAN Ltd.
*
* Heavily uses code algorithms ported from ffmpeg's libavcodec/dvbsubdec.c,
* especially the segment parsers. The original license applies to this
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "dvb-sub.h"
#include <string.h> /* memset */
#include <gst/gstutils.h> /* GST_READ_UINT16_BE */
#include <gst/base/gstbitreader.h> /* GstBitReader */
-#include "ffmpeg-colorspace.h" /* YUV_TO_RGB1_CCIR */ /* FIXME: Just give YUV data to gstreamer then? */
+
+#include "dvb-sub.h"
GST_DEBUG_CATEGORY_STATIC (dvbsub_debug);
#define GST_CAT_DEFAULT dvbsub_debug
-void
-dvb_sub_init_debug (void)
-{
- GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser");
-}
+static void dvb_sub_init (void);
/* FIXME: Are we waiting for an acquisition point before trying to do things? */
/* FIXME: In the end convert some of the guint8/16 (especially stack variables) back to gint for access efficiency */
* and signalling the API user for new bitmaps to show on screen.
*/
-#define MAX_NEG_CROP 1024
-static guint8 ff_cropTbl[256 + 2 * MAX_NEG_CROP] = { 0, };
-
-#define cm (ff_cropTbl + MAX_NEG_CROP)
+#define AYUV(y,u,v,a) (((a) << 24) | ((y) << 16) | ((u) << 8) | (v))
+#define RGBA_TO_AYUV(r,g,b,a) (((a) << 24) | ((rgb_to_y(r,g,b)) << 16) | ((rgb_to_u(r,g,b)) << 8) | (rgb_to_v(r,g,b)))
-/* FIXME: This is really ARGB... We might need this configurable for performant
- * FIXME: use in GStreamer as well if that likes RGBA more (Qt prefers ARGB) */
-#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
typedef struct DVBSubCLUT
{
struct DVBSubRegion *next;
} DVBSubRegion;
-typedef struct _DvbSubPrivate DvbSubPrivate;
-struct _DvbSubPrivate
+struct _DvbSub
{
- int fd;
DvbSubCallbacks callbacks;
gpointer user_data;
DVBSubtitleWindow display_def;
};
-#define DVB_SUB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DVB_TYPE_SUB, DvbSubPrivate))
-
-G_DEFINE_TYPE (DvbSub, dvb_sub, G_TYPE_OBJECT);
-
typedef enum
{
TOP_FIELD = 0,
BOTTOM_FIELD = 1
} DvbSubPixelDataSubBlockFieldType;
-/* FIXME: It might make sense to pass DvbSubPrivate for all the get_* functions, instead of public DvbSub */
+static inline gint
+rgb_to_y (gint r, gint g, gint b)
+{
+ gint ret;
+
+ ret = (gint) (((19595 * r) >> 16) + ((38470 * g) >> 16) + ((7471 * b) >> 16));
+ ret = CLAMP (ret, 0, 255);
+ return ret;
+}
+
+static inline gint
+rgb_to_u (gint r, gint g, gint b)
+{
+ gint ret;
+
+ ret =
+ (gint) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + ((32768 * b) >> 16) +
+ 128);
+ ret = CLAMP (ret, 0, 255);
+ return ret;
+}
+
+static inline gint
+rgb_to_v (gint r, gint g, gint b)
+{
+ gint ret;
+
+ ret =
+ (gint) (((32768 * r) >> 16) - ((27439 * g) >> 16) - ((5329 * b) >> 16) +
+ 128);
+ ret = CLAMP (ret, 0, 255);
+ return ret;
+}
+
static DVBSubObject *
get_object (DvbSub * dvb_sub, guint16 object_id)
{
- const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
- DVBSubObject *ptr = priv->object_list;
+ DVBSubObject *ptr = dvb_sub->object_list;
while (ptr && ptr->id != object_id) {
ptr = ptr->next;
static DVBSubCLUT *
get_clut (DvbSub * dvb_sub, gint clut_id)
{
- const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
- DVBSubCLUT *ptr = priv->clut_list;
+ DVBSubCLUT *ptr = dvb_sub->clut_list;
while (ptr && ptr->id != clut_id) {
ptr = ptr->next;
return ptr;
}
-// FIXME: Just pass private_data pointer directly here and in other get_* helper functions?
static DVBSubRegion *
get_region (DvbSub * dvb_sub, guint8 region_id)
{
- const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
- DVBSubRegion *ptr = priv->region_list;
+ DVBSubRegion *ptr = dvb_sub->region_list;
while (ptr && ptr->id != region_id) {
ptr = ptr->next;
static void
delete_region_display_list (DvbSub * dvb_sub, DVBSubRegion * region)
{
- const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
DVBSubObject *object, *obj2;
DVBSubObject **obj2_ptr;
DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;
*obj_disp_ptr = obj_disp->object_list_next;
if (!object->display_list) {
- obj2_ptr = (DVBSubObject **) & priv->object_list; /* FIXME: Evil casting */
+ obj2_ptr = (DVBSubObject **) & dvb_sub->object_list; /* FIXME: Evil casting */
obj2 = *obj2_ptr;
while (obj2 != object) {
static void
delete_state (DvbSub * dvb_sub)
{
- DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
DVBSubRegion *region;
- while (priv->region_list) {
- region = priv->region_list;
+ while (dvb_sub->region_list) {
+ region = dvb_sub->region_list;
- priv->region_list = region->next;
+ dvb_sub->region_list = region->next;
delete_region_display_list (dvb_sub, region);
if (region->pbuf)
g_slice_free (DVBSubRegion, region);
}
- g_slice_free_chain (DVBSubCLUT, priv->clut_list, next);
- priv->clut_list = NULL;
-
- /* Should already be null */
- if (priv->object_list)
- g_warning ("Memory deallocation error!");
-}
-
-static void
-dvb_sub_init (DvbSub * self)
-{
- DvbSubPrivate *priv;
-
- self->private_data = priv = DVB_SUB_GET_PRIVATE (self);
-
- /* TODO: Add initialization code here */
- /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */
- priv->region_list = NULL;
- priv->object_list = NULL;
- priv->page_time_out = 0; /* FIXME: Maybe 255 instead? */
- priv->pes_buffer = g_string_new (NULL);
-
- /* display/window information */
- priv->display_def.version = -1;
- priv->display_def.window_flag = 0;
- priv->display_def.display_width = 720;
- priv->display_def.display_height = 576;
-}
-
-static void
-dvb_sub_finalize (GObject * object)
-{
- DvbSub *self = DVB_SUB (object);
- DvbSubPrivate *priv = (DvbSubPrivate *) self->private_data;
- /* TODO: Add deinitalization code here */
- /* FIXME: Clear up region_list contents */
- delete_state (self); /* close_pid should have called this, but lets be sure */
- g_string_free (priv->pes_buffer, TRUE);
-
- G_OBJECT_CLASS (dvb_sub_parent_class)->finalize (object);
-}
-
-/* init static data necessary for ffmpeg-colorspace conversion */
-static void
-dsputil_static_init (void)
-{
- int i;
+ g_slice_free_chain (DVBSubCLUT, dvb_sub->clut_list, next);
+ dvb_sub->clut_list = NULL;
- for (i = 0; i < 256; i++)
- ff_cropTbl[i + MAX_NEG_CROP] = i;
- for (i = 0; i < MAX_NEG_CROP; i++) {
- ff_cropTbl[i] = 0;
- ff_cropTbl[i + MAX_NEG_CROP + 256] = 255;
- }
+ /* Should already be NULL */
+ g_warn_if_fail (dvb_sub->object_list == NULL);
}
static void
-dvb_sub_class_init (DvbSubClass * klass)
+dvb_sub_init (void)
{
int i, r, g, b, a = 0;
- GObjectClass *object_class = (GObjectClass *) klass;
- object_class->finalize = dvb_sub_finalize;
-
- g_type_class_add_private (klass, sizeof (DvbSubPrivate));
-
- dsputil_static_init (); /* Initializes ff_cropTbl table, used in YUV_TO_RGB conversion */
+ GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser");
/* Initialize the static default_clut structure, from which other clut
* structures are initialized from (to start off with default CLUTs
* as defined in the specification). */
default_clut.id = -1;
- default_clut.clut4[0] = RGBA (0, 0, 0, 0);
- default_clut.clut4[1] = RGBA (255, 255, 255, 255);
- default_clut.clut4[2] = RGBA (0, 0, 0, 255);
- default_clut.clut4[3] = RGBA (127, 127, 127, 255);
+ default_clut.clut4[0] = RGBA_TO_AYUV (0, 0, 0, 0);
+ default_clut.clut4[1] = RGBA_TO_AYUV (255, 255, 255, 255);
+ default_clut.clut4[2] = RGBA_TO_AYUV (0, 0, 0, 255);
+ default_clut.clut4[3] = RGBA_TO_AYUV (127, 127, 127, 255);
- default_clut.clut16[0] = RGBA (0, 0, 0, 0);
+ default_clut.clut16[0] = RGBA_TO_AYUV (0, 0, 0, 0);
for (i = 1; i < 16; i++) {
if (i < 8) {
r = (i & 1) ? 255 : 0;
g = (i & 2) ? 127 : 0;
b = (i & 4) ? 127 : 0;
}
- default_clut.clut16[i] = RGBA (r, g, b, 255);
+ default_clut.clut16[i] = RGBA_TO_AYUV (r, g, b, 255);
}
- default_clut.clut256[0] = RGBA (0, 0, 0, 0);
+ default_clut.clut256[0] = RGBA_TO_AYUV (0, 0, 0, 0);
for (i = 1; i < 256; i++) {
if (i < 8) {
r = (i & 1) ? 255 : 0;
break;
}
}
- default_clut.clut256[i] = RGBA (r, g, b, a);
+ default_clut.clut256[i] = RGBA_TO_AYUV (r, g, b, a);
}
}
_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
gint buf_size)
{ /* FIXME: Use guint for buf_size here and in many other places? */
- DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
DVBSubRegionDisplay *display;
DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
guint8 region_id;
guint8 page_state;
-#ifndef GST_DISABLE_GST_DEBUG
- static int counter = 0; /* FIXME: static counter? I think not.. */
-#endif
-
if (buf_size < 1)
return;
- priv->page_time_out = *buf++;
+ dvb_sub->page_time_out = *buf++;
page_state = ((*buf++) >> 2) & 3;
#ifndef GST_DISABLE_GST_DEBUG
"Normal case", "ACQUISITION POINT", "Mode Change", "RESERVED"
};
- ++counter;
- GST_DEBUG ("PAGE: %d: page_id = %u, length = %d, page_time_out = %u secs, "
- "page_state = %s", counter, page_id, buf_size, priv->page_time_out,
+ GST_DEBUG ("PAGE: page_id = %u, length = %d, page_time_out = %u secs, "
+ "page_state = %s", page_id, buf_size, dvb_sub->page_time_out,
page_state_str[page_state]);
}
#endif
delete_state (dvb_sub);
}
- tmp_display_list = priv->display_list;
- priv->display_list = NULL;
- priv->display_list_size = 0;
+ tmp_display_list = dvb_sub->display_list;
+ dvb_sub->display_list = NULL;
+ dvb_sub->display_list_size = 0;
while (buf + 5 < buf_end) {
region_id = *buf++;
*tmp_ptr = display->next;
- display->next = priv->display_list;
- priv->display_list = display;
- priv->display_list_size++;
+ display->next = dvb_sub->display_list;
+ dvb_sub->display_list = display;
+ dvb_sub->display_list_size++;
- GST_LOG ("PAGE %d: REGION information: ID = %u, address = %ux%u",
- counter, region_id, display->x_pos, display->y_pos);
+ GST_LOG ("PAGE: REGION information: ID = %u, address = %ux%u", region_id,
+ display->x_pos, display->y_pos);
}
while (tmp_display_list) {
_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
gint buf_size)
{
- DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
-
const guint8 *buf_end = buf + buf_size;
guint8 region_id;
guint16 object_id;
if (!region) { /* Create a new region */
region = g_slice_new0 (DVBSubRegion);
region->id = region_id;
- region->next = priv->region_list;
- priv->region_list = region;
+ region->next = dvb_sub->region_list;
+ dvb_sub->region_list = region;
}
fill = ((*buf++) >> 3) & 1;
object->id = object_id;
- object->next = priv->object_list;
- priv->object_list = object;
+ object->next = dvb_sub->object_list;
+ dvb_sub->object_list = object;
}
object->type = (*buf) >> 6;
_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf,
gint buf_size)
{
- DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
-
const guint8 *buf_end = buf + buf_size;
guint8 clut_id;
DVBSubCLUT *clut;
int entry_id, depth, full_range;
int y, cr, cb, alpha;
- int r, g, b, r_add, g_add, b_add;
GST_MEMDUMP ("DVB clut packet", buf, buf_size);
clut = get_clut (dvb_sub, clut_id);
if (!clut) {
- clut = g_slice_new (DVBSubCLUT); /* FIXME-MEMORY-LEAK: This seems to leak per valgrind */
+ clut = g_slice_new (DVBSubCLUT);
memcpy (clut, &default_clut, sizeof (DVBSubCLUT));
clut->id = clut_id;
- clut->next = priv->clut_list;
- priv->clut_list = clut;
+ clut->next = dvb_sub->clut_list;
+ dvb_sub->clut_list = clut;
}
while (buf + 4 < buf_end) {
if (y == 0)
alpha = 0xff;
- YUV_TO_RGB1_CCIR (cb, cr);
- YUV_TO_RGB2_CCIR (r, g, b, y);
-
- GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, r, g, b,
+ GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, y, cb, cr,
alpha);
if (depth & 0x80)
- clut->clut4[entry_id] = RGBA (r, g, b, 255 - alpha);
+ clut->clut4[entry_id] = AYUV (y, cb, cr, 255 - alpha);
if (depth & 0x40)
- clut->clut16[entry_id] = RGBA (r, g, b, 255 - alpha);
+ clut->clut16[entry_id] = AYUV (y, cb, cr, 255 - alpha);
if (depth & 0x20)
- clut->clut256[entry_id] = RGBA (r, g, b, 255 - alpha);
+ clut->clut256[entry_id] = AYUV (y, cb, cr, 255 - alpha);
}
}
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) {
guint run_length = 0, clut_index = 0;
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 2);
+
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
if (bits) { /* 2-bit_pixel-code */
run_length = 1;
clut_index = bits;
} else { /* 2-bit_zero */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 1);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
if (bits == 1) { /* switch_1 == '1' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3);
run_length += 3;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
} else { /* switch_1 == '0' */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 1);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
if (bits == 1) { /* switch_2 == '1' */
run_length = 1; /* 1x pseudo-colour '00' */
} else { /* switch_2 == '0' */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 2);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
switch (bits) { /* switch_3 */
case 0x0: /* end of 2-bit/pixel_code_string */
stop_parsing = TRUE;
run_length = 2;
break;
case 0x2: /* the following 6 bits contain run length coded pixel data */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
run_length += 12;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
break;
case 0x3: /* the following 10 bits contain run length coded pixel data */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
run_length += 29;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
break;
}
}
GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer, "
"dbuf_len left is %d pixels", run_length, clut_index, dbuf_len);
- if (!(non_mod == 1 && bits == 1))
+ if (!(non_mod == 1 && clut_index == 1))
memset (destbuf, clut_index, run_length);
destbuf += run_length;
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) {
guint run_length = 0, clut_index = 0;
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 4);
+
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
if (bits) {
run_length = 1;
clut_index = bits;
} else {
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 1);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
if (bits == 0) { /* switch_1 == '0' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 3);
if (!run_length) {
stop_parsing = TRUE;
} else {
run_length += 2;
}
} else { /* switch_1 == '1' */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 1);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
if (bits == 0) { /* switch_2 == '0' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 2);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
run_length += 4;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
} else { /* switch_2 == '1' */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 2);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 2);
switch (bits) {
case 0x0: /* switch_3 == '00' */
run_length = 1; /* 1 pixel of pseudo-color 0 */
run_length = 2; /* 2 pixels of pseudo-color 0 */
break;
case 0x2: /* switch_3 == '10' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
run_length += 9;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
break;
case 0x3: /* switch_3 == '11' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
run_length += 25;
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 4);
break;
}
}
GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer; "
"dbuf_len left is %d pixels", run_length, clut_index, dbuf_len);
- if (!(non_mod == 1 && bits == 1))
+ if (!(non_mod == 1 && clut_index == 1))
memset (destbuf, clut_index, run_length);
destbuf += run_length;
/* Rephrased - it's better to work with bytes with default value '0' instead of reading from memory we don't own. */
while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) {
guint run_length = 0, clut_index = 0;
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 8);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
if (bits) { /* 8-bit_pixel-code */
run_length = 1;
clut_index = bits;
} else { /* 8-bit_zero */
- gst_bit_reader_get_bits_uint32 (&gb, &bits, 1);
+ bits = gst_bit_reader_get_bits_uint32_unchecked (&gb, 1);
if (bits == 0) { /* switch_1 == '0' */
/* run_length_1-127 for pseudo-colour _entry) '0x00' */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7);
if (run_length == 0) { /* end_of_string_signal */
stop_parsing = TRUE;
}
} else { /* switch_1 == '1' */
/* run_length_3-127 */
- gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7);
- gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 8);
+ run_length = gst_bit_reader_get_bits_uint32_unchecked (&gb, 7);
+ clut_index = gst_bit_reader_get_bits_uint32_unchecked (&gb, 8);
if (run_length < 3) {
GST_WARNING ("runlength value was %u, but the spec requires it "
GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer; "
"dbuf_len left is %d pixels", run_length, clut_index, dbuf_len);
- if (!(non_mod == 1 && bits == 1))
+ if (!(non_mod == 1 && clut_index == 1))
memset (destbuf, clut_index, run_length);
destbuf += run_length;
gint buf_size)
{
int dds_version, info_byte;
- DvbSubPrivate *ctx = dvb_sub->private_data;
if (buf_size < 5)
return -1;
info_byte = *buf++;
dds_version = info_byte >> 4;
- if (ctx->display_def.version == dds_version)
+ if (dvb_sub->display_def.version == dds_version)
return 0; /* already have this display definition version */
- ctx->display_def.version = dds_version;
- ctx->display_def.display_width = GST_READ_UINT16_BE (buf) + 1;
+ dvb_sub->display_def.version = dds_version;
+ dvb_sub->display_def.display_width = GST_READ_UINT16_BE (buf) + 1;
buf += 2;
- ctx->display_def.display_height = GST_READ_UINT16_BE (buf) + 1;
+ dvb_sub->display_def.display_height = GST_READ_UINT16_BE (buf) + 1;
buf += 2;
- ctx->display_def.window_flag = info_byte & 1 << 3;
+ dvb_sub->display_def.window_flag = info_byte & 1 << 3;
- if (buf_size >= 13 && ctx->display_def.window_flag) {
- ctx->display_def.window_x = GST_READ_UINT16_BE (buf);
+ if (buf_size >= 13 && dvb_sub->display_def.window_flag) {
+ dvb_sub->display_def.window_x = GST_READ_UINT16_BE (buf);
buf += 2;
- ctx->display_def.window_y = GST_READ_UINT16_BE (buf);
+ dvb_sub->display_def.window_y = GST_READ_UINT16_BE (buf);
buf += 2;
- ctx->display_def.window_width =
- GST_READ_UINT16_BE (buf) - ctx->display_def.window_x + 1;
+ dvb_sub->display_def.window_width =
+ GST_READ_UINT16_BE (buf) - dvb_sub->display_def.window_x + 1;
buf += 2;
- ctx->display_def.window_height =
- GST_READ_UINT16_BE (buf) - ctx->display_def.window_y + 1;
+ dvb_sub->display_def.window_height =
+ GST_READ_UINT16_BE (buf) - dvb_sub->display_def.window_y + 1;
buf += 2;
}
_dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id,
guint8 * buf, gint buf_size, guint64 pts)
{
- DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data;
-
- DVBSubtitles *sub = g_slice_new0 (DVBSubtitles);
-
- DVBSubRegion *region;
DVBSubRegionDisplay *display;
- DVBSubtitleRect *rect;
+ DVBSubtitles *sub;
DVBSubCLUT *clut;
guint32 *clut_table;
int i;
- static unsigned counter = 0; /* DEBUG use only *//* FIXME: get rid */
-
GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id, buf_size);
- sub->rects = NULL;
+ sub = g_slice_new0 (DVBSubtitles);
+
#if 0 /* FIXME: PTS stuff not figured out yet */
sub->start_display_time = 0;
sub->end_display_time = priv->page_time_out * 1000;
sub->format = 0; /* 0 = graphics */
#endif
- sub->num_rects = priv->display_list_size;
-
- if (sub->num_rects > 0) {
- // FIXME-MEMORY-LEAK: This structure is not freed up yet
- sub->rects = g_malloc0 (sizeof (*sub->rects) * sub->num_rects); /* GSlice? */
- for (i = 0; i < sub->num_rects; i++)
- sub->rects[i] = g_malloc0 (sizeof (*sub->rects[i])); /* GSlice? */
- }
+ /* N.B. g_new0() will return NULL if num_rects is 0 */
+ sub->num_rects = dvb_sub->display_list_size;
+ sub->rects = g_new0 (DVBSubtitleRect, sub->num_rects);
i = 0;
/* copy subtitle display and window information */
- sub->display_def = priv->display_def;
+ sub->display_def = dvb_sub->display_def;
+
+ for (display = dvb_sub->display_list; display; display = display->next) {
+ DVBSubtitleRect *rect;
+ DVBSubRegion *region;
- for (display = priv->display_list; display; display = display->next) {
region = get_region (dvb_sub, display->region_id);
- rect = sub->rects[i];
if (!region)
continue;
+ rect = &sub->rects[i];
rect->x = display->x_pos;
rect->y = display->y_pos;
rect->w = region->width;
rect->pict.data = g_malloc (region->buf_size); /* FIXME: Can we use GSlice here? */
memcpy (rect->pict.data, region->pbuf, region->buf_size);
- ++counter;
- GST_DEBUG ("DISPLAY: an object rect created: number %u, iteration %u, "
- "pos: %d:%d, size: %dx%d", counter, i, rect->x, rect->y, rect->w,
- rect->h);
+ GST_DEBUG ("DISPLAY: an object rect created: iteration %u, "
+ "pos: %d:%d, size: %dx%d", i, rect->x, rect->y, rect->w, rect->h);
GST_MEMDUMP ("rect->pict.data content", rect->pict.data, region->buf_size);
}
sub->pts = pts;
- sub->page_time_out = priv->page_time_out;
+ sub->page_time_out = dvb_sub->page_time_out;
sub->num_rects = i;
- if (priv->callbacks.new_data) {
- priv->callbacks.new_data (dvb_sub, sub, priv->user_data);
+ if (dvb_sub->callbacks.new_data) {
+ dvb_sub->callbacks.new_data (dvb_sub, sub, dvb_sub->user_data);
} else {
/* No-one responsible to clean up memory, so do it ourselves */
/* FIXME: Just don't bother with all this palette image creation in the first place then... */
dvb_subtitles_free (DVBSubtitles * sub)
{
int i;
- DVBSubtitleRect *rect;
if (sub == NULL)
return;
/* Now free up all the temporary memory we allocated */
for (i = 0; i < sub->num_rects; ++i) {
- rect = sub->rects[i];
-
- g_free (rect->pict.palette);
- g_free (rect->pict.data);
- g_free (rect);
+ g_free (sub->rects[i].pict.palette);
+ g_free (sub->rects[i].pict.data);
}
g_free (sub->rects);
g_slice_free (DVBSubtitles, sub);
}
-/**
- * dvb_sub_new:
- *
- * Creates a new #DvbSub.
- *
- * Return value: a newly created #DvbSub
- */
DvbSub *
dvb_sub_new (void)
{
- DvbSub *dvbsub = g_object_new (DVB_TYPE_SUB, NULL);
+ static gsize inited = 0;
+ DvbSub *sub;
+
+ if (g_once_init_enter (&inited)) {
+ dvb_sub_init ();
+ g_once_init_leave (&inited, TRUE);
+ }
+
+ sub = g_slice_new0 (DvbSub);
+
+ /* TODO: Add initialization code here */
+ /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */
+ sub->region_list = NULL;
+ sub->object_list = NULL;
+ sub->page_time_out = 0; /* FIXME: Maybe 255 instead? */
+ sub->pes_buffer = g_string_new (NULL);
- return dvbsub;
+ /* display/window information */
+ sub->display_def.version = -1;
+ sub->display_def.window_flag = 0;
+ sub->display_def.display_width = 720;
+ sub->display_def.display_height = 576;
+
+ return sub;
+}
+
+void
+dvb_sub_free (DvbSub * sub)
+{
+ /* TODO: Add deinitalization code here */
+ /* FIXME: Clear up region_list contents */
+ delete_state (sub);
+ while (sub->display_list) {
+ DVBSubRegionDisplay *tmp = sub->display_list->next;
+ g_slice_free (DVBSubRegionDisplay, sub->display_list);
+ sub->display_list = tmp;
+ }
+ g_string_free (sub->pes_buffer, TRUE);
+ g_slice_free (DvbSub, sub);
}
#define DVB_SUB_SEGMENT_PAGE_COMPOSITION 0x10
dvb_sub_set_callbacks (DvbSub * dvb_sub, DvbSubCallbacks * callbacks,
gpointer user_data)
{
- DvbSubPrivate *priv;
-
g_return_if_fail (dvb_sub != NULL);
- g_return_if_fail (DVB_IS_SUB (dvb_sub));
g_return_if_fail (callbacks != NULL);
- priv = (DvbSubPrivate *) dvb_sub->private_data;
-
- priv->callbacks = *callbacks;
- priv->user_data = user_data;
+ dvb_sub->callbacks = *callbacks;
+ dvb_sub->user_data = user_data;
}