summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2009-11-04 20:27:08 +0000
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2009-11-04 20:27:08 +0000
commit2af40655557ffc8197e3e59b9428168c2454a68b (patch)
treec1891ff45d933b56a8b6ab1154ffde91cb53d8e5
parent27bff654d01de5a27a766b4d0c8dee16e4554358 (diff)
parentf7301e347937dfa9fa6879ff9376f1b3a2642e78 (diff)
downloadxine-lib-2af40655557ffc8197e3e59b9428168c2454a68b.tar.gz
xine-lib-2af40655557ffc8197e3e59b9428168c2454a68b.tar.bz2
Merge.
-rw-r--r--src/libspuhdmv/xine_hdmv_decoder.c324
1 files changed, 188 insertions, 136 deletions
diff --git a/src/libspuhdmv/xine_hdmv_decoder.c b/src/libspuhdmv/xine_hdmv_decoder.c
index 358cb0b72..ba4487bf6 100644
--- a/src/libspuhdmv/xine_hdmv_decoder.c
+++ b/src/libspuhdmv/xine_hdmv_decoder.c
@@ -47,7 +47,7 @@
#define TRACE(x...) printf(x)
/*#define TRACE(x...) */
-#define ERROR(x...) fprintf(stderr, x)
+#define ERROR(x...) fprintf(stderr, "spuhdmv: " x)
/*#define ERROR(x...) lprintf(x) */
/*
@@ -59,6 +59,8 @@ struct subtitle_clut_s {
uint32_t color[256];
uint8_t trans[256];
subtitle_clut_t *next;
+
+ int shown;
};
/*
@@ -74,11 +76,15 @@ struct subtitle_object_s {
uint num_rle;
size_t data_size;
+#if 0
uint8_t *raw_data; /* partial RLE data in HDMV format */
size_t raw_data_len;
size_t raw_data_size;
+#endif
subtitle_object_t *next;
+
+ int shown;
};
/*
@@ -91,6 +97,8 @@ struct window_def_s {
uint16_t width, height;
window_def_t *next;
+
+ int shown;
};
@@ -110,9 +118,79 @@ struct composition_object_s {
uint16_t crop_width, crop_height;
composition_object_t *next;
+
+ int shown;
+};
+
+typedef struct composition_descriptor_s composition_descriptor_t;
+struct composition_descriptor_s {
+ uint16_t number;
+ uint8_t state;
+};
+
+typedef struct presentation_segment_s presentation_segment_t;
+struct presentation_segment_s {
+ composition_descriptor_t comp_descr;
+
+ uint8_t palette_update_flag;
+ uint8_t palette_id_ref;
+ uint8_t object_number;
+
+ composition_object_t *comp_objs;
+
+ presentation_segment_t *next;
+
+ int64_t pts;
+ int shown;
};
/*
+ * list handling
+ */
+
+#define LIST_REPLACE(list, obj, FREE_FUNC) \
+ do { \
+ uint id = obj->id; \
+ \
+ /* insert to list */ \
+ obj->next = list; \
+ list = obj; \
+ \
+ /* remove old */ \
+ while (obj->next && obj->next->id != id) \
+ obj = obj->next; \
+ if (obj->next) { \
+ void *tmp = (void*)obj->next; \
+ obj->next = obj->next->next; \
+ FREE_FUNC(tmp); \
+ } \
+ } while (0);
+
+#define LIST_DESTROY(list, FREE_FUNC) \
+ while (list) { \
+ void *tmp = (void*)list; \
+ list = list->next; \
+ FREE_FUNC(tmp); \
+ }
+
+static void free_subtitle_object(void *ptr)
+{
+ if (ptr) {
+ free(((subtitle_object_t*)ptr)->rle);
+ free(ptr);
+ }
+}
+static void free_presentation_segment(void *ptr)
+{
+ if (ptr) {
+ presentation_segment_t *seg = (presentation_segment_t*)ptr;
+ LIST_DESTROY(seg->comp_objs, free);
+ free(ptr);
+ }
+}
+
+
+/*
* segment_buffer_t
*
* assemble and decode segments
@@ -397,14 +475,14 @@ static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf)
segbuf_decode_rle (buf, obj);
if (buf->error) {
- free(obj);
+ free_subtitle_object(obj);
return NULL;
}
} else {
ERROR(" TODO: APPEND RLE, length %d bytes\n", buf->segment_len - 4);
/* TODO */
- free(obj);
+ free_subtitle_object(obj);
return NULL;
}
@@ -443,12 +521,6 @@ static int segbuf_decode_video_descriptor(segment_buffer_t *buf)
return buf->error;
}
-typedef struct composition_descriptor_s composition_descriptor_t;
-struct composition_descriptor_s {
- uint16_t number;
- uint8_t state;
-};
-
static int segbuf_decode_composition_descriptor(segment_buffer_t *buf, composition_descriptor_t *descr)
{
descr->number = segbuf_get_u16(buf);
@@ -490,9 +562,38 @@ static composition_object_t *segbuf_decode_composition_object(segment_buffer_t *
return cobj;
}
+static presentation_segment_t *segbuf_decode_presentation_segment(segment_buffer_t *buf)
+{
+ presentation_segment_t *seg = calloc(1, sizeof(presentation_segment_t));
+ int index;
+
+ segbuf_decode_video_descriptor (buf);
+ segbuf_decode_composition_descriptor (buf, &seg->comp_descr);
+
+ seg->palette_update_flag = !!((segbuf_get_u8(buf)) & 0x80);
+ seg->palette_id_ref = segbuf_get_u8 (buf);
+ seg->object_number = segbuf_get_u8 (buf);
+
+ TRACE(" presentation_segment: object_number %d, palette %d\n",
+ seg->object_number, seg->palette_id_ref);
+
+ for (index = 0; index < seg->object_number; index++) {
+ composition_object_t *cobj = segbuf_decode_composition_object (buf);
+ cobj->next = seg->comp_objs;
+ seg->comp_objs = cobj;
+ }
+
+ if (buf->error) {
+ free_presentation_segment(seg);
+ return NULL;
+ }
+
+ return seg;
+}
+
static rle_elem_t *copy_crop_rle(subtitle_object_t *obj, composition_object_t *cobj)
{
- /* TODO: exec cropping here (w,h sized image from pos x,y) */
+ /* TODO: cropping (w,h sized image from pos x,y) */
rle_elem_t *rle = calloc (obj->num_rle, sizeof(rle_elem_t));
memcpy (rle, obj->rle, obj->num_rle * sizeof(rle_elem_t));
@@ -516,57 +617,17 @@ typedef struct spuhdmv_decoder_s {
segment_buffer_t *buf;
- subtitle_clut_t *cluts;
- subtitle_object_t *objects;
- window_def_t *windows;
+ subtitle_clut_t *cluts;
+ subtitle_object_t *objects;
+ window_def_t *windows;
+ presentation_segment_t *segments;
+
int overlay_handles[MAX_OBJECTS];
int64_t pts;
} spuhdmv_decoder_t;
-#define LIST_REPLACE_OLD(type, list, obj) \
- do { \
- /* insert to list */ \
- obj->next = list; \
- list = obj; \
-\
- /* remove old */ \
- type *i = list; \
- while (i->next && i->next->id != obj->id) \
- i = i->next; \
- if (i->next) { \
- void *tmp = (void*)i->next; \
- i->next = i->next->next; \
- free(tmp); \
- } \
- } while (0);
-
-#define LIST_REPLACE(list, obj) \
- do { \
- uint id = obj->id; \
- \
- /* insert to list */ \
- obj->next = list; \
- list = obj; \
- \
- /* remove old */ \
- while (obj->next && obj->next->id != id) \
- obj = obj->next; \
- if (obj->next) { \
- void *tmp = (void*)obj->next; \
- obj->next = obj->next->next; \
- free(tmp); \
- } \
- } while (0);
-
-#define LIST_DESTROY(list) \
- while (list) { \
- void *tmp = (void*)list; \
- list = list->next; \
- free (tmp); \
- }
-
static int decode_palette(spuhdmv_decoder_t *this)
{
/* decode */
@@ -574,7 +635,7 @@ static int decode_palette(spuhdmv_decoder_t *this)
if (!clut)
return 1;
- LIST_REPLACE (this->cluts, clut);
+ LIST_REPLACE (this->cluts, clut, free);
return 0;
}
@@ -586,7 +647,7 @@ static int decode_object(spuhdmv_decoder_t *this)
if (!obj)
return 1;
- LIST_REPLACE (this->objects, obj);
+ LIST_REPLACE (this->objects, obj, free_subtitle_object);
return 0;
}
@@ -598,13 +659,30 @@ static int decode_window_definition(spuhdmv_decoder_t *this)
if (!wnd)
return 1;
- LIST_REPLACE (this->windows, wnd);
+ LIST_REPLACE (this->windows, wnd, free);
+
+ return 0;
+}
+
+static int decode_presentation_segment(spuhdmv_decoder_t *this)
+{
+ /* decode */
+ presentation_segment_t *seg = segbuf_decode_presentation_segment(this->buf);
+ if (!seg)
+ return 1;
+
+ seg->pts = this->pts;
+
+ /* replace */
+ if (this->segments)
+ LIST_DESTROY(this->segments, free_presentation_segment);
+ this->segments = seg;
return 0;
}
static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uint palette_id_ref,
- int overlay_index, int64_t pts)
+ int overlay_index, int64_t pts, int force_update)
{
video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager(this->stream->video_out);
metronom_t *metronom = this->stream->metronom;
@@ -616,21 +694,16 @@ static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uin
while (clut && clut->id != palette_id_ref)
clut = clut->next;
if (!clut) {
- ERROR(" fill_overlay: clut %d not found !\n", palette_id_ref);
+ TRACE(" show_overlay: clut %d not found !\n", palette_id_ref);
return -1;
}
- /* copy palette to xine overlay */
- overlay.rgb_clut = 0;
- memcpy(overlay.color, clut->color, sizeof(uint32_t) * 256);
- memcpy(overlay.trans, clut->trans, sizeof(uint8_t) * 256);
-
/* find RLE image */
subtitle_object_t *obj = this->objects;
while (obj && obj->id != cobj->object_id_ref)
obj = obj->next;
if (!obj) {
- ERROR(" fill_overlay: object %d not found !\n", cobj->object_id_ref);
+ TRACE(" show_overlay: object %d not found !\n", cobj->object_id_ref);
return -1;
}
@@ -639,10 +712,20 @@ static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uin
while (wnd && wnd->id != cobj->window_id_ref)
wnd = wnd->next;
if (!wnd) {
- ERROR(" fill_overlay: window %d not found !\n", cobj->window_id_ref);
+ TRACE(" show_overlay: window %d not found !\n", cobj->window_id_ref);
return -1;
}
+ /* do not show again if all elements are unchanged */
+ if (!force_update && clut->shown && obj->shown && wnd->shown && cobj->shown)
+ return 0;
+ clut->shown = obj->shown = wnd->shown = cobj->shown = 1;
+
+ /* copy palette to xine overlay */
+ overlay.rgb_clut = 0;
+ memcpy(overlay.color, clut->color, sizeof(uint32_t) * 256);
+ memcpy(overlay.trans, clut->trans, sizeof(uint8_t) * 256);
+
/* copy and crop RLE image to xine overlay */
overlay.width = obj->width;
overlay.height = obj->height;
@@ -688,41 +771,9 @@ static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uin
ovl_manager->add_event (ovl_manager, (void *)&event);
- obj->rle = NULL;
-
return 0;
}
-typedef struct presentation_segment_s presentation_segment_t;
-struct presentation_segment_s {
- composition_descriptor_t comp_descr;
-
- uint8_t palette_update_flag;
- uint8_t palette_id_ref;
- uint8_t object_number;
-
- composition_object_t *comp_objs;
-
- presentation_segment_t *next;
-
- int64_t pts;
-};
-
-static void show_overlays(spuhdmv_decoder_t *this, presentation_segment_t *pseg)
-{
- composition_object_t *cobj = pseg->comp_objs;
- int i;
-
- for (i = 0; i < pseg->object_number; i++) {
- if (!cobj) {
- ERROR("show_overlays: composition object %d missing !\n", i);
- } else {
- show_overlay(this, cobj, pseg->palette_id_ref, i, pseg->pts);
- cobj = cobj->next;
- }
- }
-}
-
static void hide_overlays(spuhdmv_decoder_t *this, int64_t pts)
{
video_overlay_event_t event = {0};
@@ -748,38 +799,46 @@ static void hide_overlays(spuhdmv_decoder_t *this, int64_t pts)
}
}
-static int decode_presentation_segment(spuhdmv_decoder_t *this)
+static void update_overlays(spuhdmv_decoder_t *this)
{
- presentation_segment_t p = {};
- segment_buffer_t *buf = this->buf;
- int index;
+ presentation_segment_t *pseg = this->segments;
- segbuf_decode_video_descriptor (this->buf);
- segbuf_decode_composition_descriptor (this->buf, &p.comp_descr);
+ while (pseg) {
- p.palette_update_flag = !!((segbuf_get_u8(buf)) & 0x80);
- p.palette_id_ref = segbuf_get_u8 (buf);
- p.object_number = segbuf_get_u8 (buf);
+ if (!pseg->comp_descr.state) {
- TRACE(" presentation_segment: object_number %d, palette %d\n",
- p.object_number, p.palette_id_ref);
+ /* HIDE */
+ if (!pseg->shown)
+ hide_overlays (this, pseg->pts);
- p.pts = this->pts; /* !! todo - use it ? */
+ } else {
- for (index = 0; index < p.object_number; index++) {
- composition_object_t *cobj = segbuf_decode_composition_object (this->buf);
- cobj->next = p.comp_objs;
- p.comp_objs = cobj;
- }
+ /* SHOW */
+ composition_object_t *cobj = pseg->comp_objs;
+ int i;
+
+ for (i = 0; i < pseg->object_number; i++) {
+ if (!cobj) {
+ ERROR("show_overlays: composition object %d missing !\n", i);
+ } else {
+ show_overlay(this, cobj, pseg->palette_id_ref, i, pseg->pts, !pseg->shown);
+ cobj = cobj->next;
+ }
+ }
+ }
- if (!p.comp_descr.state) {
- hide_overlays (this, this->pts);
- } else {
- show_overlays (this, &p);
- LIST_DESTROY (p.comp_objs);
+ pseg->shown = 1;
+
+ pseg = pseg->next;
}
+}
- return buf->error;
+static void free_objs(spuhdmv_decoder_t *this)
+{
+ LIST_DESTROY (this->cluts, free);
+ LIST_DESTROY (this->objects, free_subtitle_object);
+ LIST_DESTROY (this->windows, free);
+ LIST_DESTROY (this->segments, free_presentation_segment);
}
static void decode_segment(spuhdmv_decoder_t *this)
@@ -809,13 +868,8 @@ static void decode_segment(spuhdmv_decoder_t *this)
break;
case 0x80:
TRACE(" segment: END OF DISPLAY\n");
- {
- int64_t pts = xine_get_current_vpts(this->stream) -
- this->stream->metronom->get_option(this->stream->metronom,
- METRONOM_VPTS_OFFSET);
- TRACE(" * current pts = %ld\n", pts);
- }
-
+ /* drop all cached objects */
+ free_objs(this);
break;
default:
ERROR(" segment type 0x%x unknown, skipping\n", this->buf->segment_type);
@@ -824,11 +878,13 @@ static void decode_segment(spuhdmv_decoder_t *this)
if (this->buf->error) {
ERROR("*** DECODE ERROR ***\n");
}
+
+ update_overlays (this);
}
static void close_osd(spuhdmv_decoder_t *this)
{
- video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out);
+ video_overlay_manager_t *ovl_manager = this->stream->video_out->get_overlay_manager (this->stream->video_out);
int i = 0;
while (this->overlay_handles[i] >= 0) {
@@ -873,9 +929,7 @@ static void spudec_reset (spu_decoder_t * this_gen)
if (this->buf)
segbuf_reset(this->buf);
- LIST_DESTROY (this->cluts);
- LIST_DESTROY (this->objects);
- LIST_DESTROY (this->windows);
+ free_objs(this);
close_osd(this);
}
@@ -894,9 +948,7 @@ static void spudec_dispose (spu_decoder_t *this_gen)
close_osd (this);
segbuf_dispose (this->buf);
- LIST_DESTROY (this->cluts);
- LIST_DESTROY (this->objects);
- LIST_DESTROY (this->windows);
+ free_objs(this);
free (this);
}