summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2011-08-23 20:18:22 +0100
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2011-08-23 20:18:22 +0100
commitb097a80fb2d9100e02f2fdaf62fe3d408f73763f (patch)
tree930fda0d620d73f453e7be7eb51aad28de3395cf
parent53ec0b8ab9e7076d84221bbd5ea84978239a1afc (diff)
parentedb68926aced0739f3e62ea2501bc32326c02f86 (diff)
downloadxine-lib-b097a80fb2d9100e02f2fdaf62fe3d408f73763f.tar.gz
xine-lib-b097a80fb2d9100e02f2fdaf62fe3d408f73763f.tar.bz2
Merge from 1.1.
--HG-- rename : src/xine-engine/buffer.h => include/xine/buffer.h rename : src/libxineadec/xine_lpcm_decoder.c => src/audio_dec/xine_lpcm_decoder.c rename : src/libspuhdmv/xine_hdmv_decoder.c => src/spu_dec/spuhdmv_decoder.c
-rw-r--r--include/xine/buffer.h1
-rw-r--r--src/audio_dec/xine_lpcm_decoder.c8
-rw-r--r--src/combined/ffmpeg/ff_audio_decoder.c36
-rw-r--r--src/combined/ffmpeg/ff_video_decoder.c6
-rw-r--r--src/combined/ffmpeg/xine_video.list3
-rw-r--r--src/demuxers/demux_matroska.c23
-rw-r--r--src/demuxers/matroska.h1
-rw-r--r--src/spu_dec/spuhdmv_decoder.c278
-rw-r--r--src/xine-engine/audio_decoder.c3
-rw-r--r--src/xine-engine/buffer_types.c8
-rw-r--r--src/xine-engine/video_out.c59
11 files changed, 301 insertions, 125 deletions
diff --git a/include/xine/buffer.h b/include/xine/buffer.h
index 35c793439..95cdcb69a 100644
--- a/include/xine/buffer.h
+++ b/include/xine/buffer.h
@@ -191,6 +191,7 @@ extern "C" {
#define BUF_VIDEO_VC1 0x02650000
#define BUF_VIDEO_VMNC 0x02660000
#define BUF_VIDEO_SNOW 0x02670000
+#define BUF_VIDEO_VP8 0x02680000
/*@}*/
/**
diff --git a/src/audio_dec/xine_lpcm_decoder.c b/src/audio_dec/xine_lpcm_decoder.c
index 7b9b4a81b..59f847f5c 100644
--- a/src/audio_dec/xine_lpcm_decoder.c
+++ b/src/audio_dec/xine_lpcm_decoder.c
@@ -120,8 +120,12 @@ static void lpcm_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) {
num_channels = channels[(buf->decoder_info[2] >> (16+4)) & 0x0f];
switch ((buf->decoder_info[2] >> (24+6)) & 0x03) {
case 1: bits_per_sample = 16; break;
- case 2: bits_per_sample = 20; break;
- case 3: bits_per_sample = 24; special_dvd_audio = 1; break;
+ case 2: /*bits_per_sample = 20; break;*/
+ /* fall thru. Samples are 0-padded to 24 bits, and
+ * converted later to 16 bits by dropping 8 lowest bits.
+ * this needs to be changed if audio out some day accepts 24bit samples.
+ */
+ case 3: bits_per_sample = 24; break;
default: bits_per_sample = 0; break;
}
switch ((buf->decoder_info[2] >> 16) & 0x0f) {
diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c
index 0367d0e50..db2dc8fa2 100644
--- a/src/combined/ffmpeg/ff_audio_decoder.c
+++ b/src/combined/ffmpeg/ff_audio_decoder.c
@@ -80,13 +80,41 @@ typedef struct ff_audio_decoder_s {
#include "ff_audio_list.h"
+#define malloc16(s) realloc16(NULL,s)
+#define free16(p) realloc16(p,0)
+
+static void *realloc16 (void *m, size_t s) {
+ unsigned int diff, diff2;
+ unsigned char *p = m, *q;
+ if (p) {
+ diff = p[-1];
+ if (s == 0) {
+ free (p - diff);
+ return (NULL);
+ }
+ q = realloc (p - diff, s + 16);
+ if (!q) return (q);
+ diff2 = 16 - ((unsigned int)q & 15);
+ if (diff2 != diff) memmove (q + diff2, q + diff, s);
+ } else {
+ if (s == 0) return (NULL);
+ q = malloc (s + 16);
+ if (!q) return (q);
+ diff2 = 16 - ((unsigned int)q & 15);
+ }
+ q += diff2;
+ q[-1] = diff2;
+ return (q);
+}
+
+
static void ff_audio_ensure_buffer_size(ff_audio_decoder_t *this, int size) {
if (size > this->bufsize) {
this->bufsize = size + size / 2;
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("ffmpeg_audio_dec: increasing buffer to %d to avoid overflow.\n"),
this->bufsize);
- this->buf = realloc( this->buf, this->bufsize );
+ this->buf = realloc16 (this->buf, this->bufsize);
}
}
@@ -246,7 +274,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf)
this->size = 0;
- this->decode_buffer = calloc(1, AVCODEC_MAX_AUDIO_FRAME_SIZE);
+ this->decode_buffer = malloc16 (AVCODEC_MAX_AUDIO_FRAME_SIZE);
return;
}
@@ -454,8 +482,8 @@ static void ff_audio_dispose (audio_decoder_t *this_gen) {
this->stream->audio_out->close (this->stream->audio_out, this->stream);
this->output_open = 0;
- free(this->buf);
- free(this->decode_buffer);
+ free16 (this->buf);
+ free16 (this->decode_buffer);
if(this->context && this->context->extradata)
free(this->context->extradata);
diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c
index b20ccad70..5e4967f6c 100644
--- a/src/combined/ffmpeg/ff_video_decoder.c
+++ b/src/combined/ffmpeg/ff_video_decoder.c
@@ -318,6 +318,10 @@ static void init_video_codec (ff_video_decoder_t *this, unsigned int codec_type)
this->context->flags |= CODEC_FLAG_EMU_EDGE;
}
+ /* TJ. without this, it wont work at all on my machine */
+ this->context->codec_id = this->codec->id;
+ this->context->codec_type = this->codec->type;
+
if (this->class->choose_speed_over_accuracy)
this->context->flags2 |= CODEC_FLAG2_FAST;
@@ -898,6 +902,8 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu
switch (codec_type) {
case BUF_VIDEO_RV10:
case BUF_VIDEO_RV20:
+ case BUF_VIDEO_RV30:
+ case BUF_VIDEO_RV40:
this->bih.biWidth = _X_BE_16(&this->buf[12]);
this->bih.biHeight = _X_BE_16(&this->buf[14]);
diff --git a/src/combined/ffmpeg/xine_video.list b/src/combined/ffmpeg/xine_video.list
index 144bbe1c2..009f4dafd 100644
--- a/src/combined/ffmpeg/xine_video.list
+++ b/src/combined/ffmpeg/xine_video.list
@@ -21,6 +21,8 @@ I263 H263I ITU H.263
H263 H263 H.263
RV10 RV10 Real Video 1.0
RV20 RV20 Real Video 2.0
+RV30 RV30 Real Video 3.0
+RV40 RV40 Real Video 4.0
IV31 INDEO3 Indeo Video 3.1
IV32 INDEO3 Indeo Video 3.2
SORENSON_V1 SVQ1 Sorenson Video 1
@@ -31,6 +33,7 @@ VP31 VP3 On2 VP3.1
VP5 VP5 On2 VP5
VP6 VP6 On2 VP6
VP6F VP6F On2 VP6
+VP8 VP8 On2 VP8
4XM 4XM 4X Video
CINEPAK CINEPAK Cinepak
MSVC MSVIDEO1 Microsoft Video 1
diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c
index 6392aaac0..4fab784f7 100644
--- a/src/demuxers/demux_matroska.c
+++ b/src/demuxers/demux_matroska.c
@@ -1333,6 +1333,29 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
lprintf("MATROSKA_CODEC_ID_V_MPEG2\n");
track->buf_type = BUF_VIDEO_MPEG;
init_codec = init_codec_video;
+ } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_VP8)) {
+ xine_bmiheader *bih;
+
+ lprintf("MATROSKA_CODEC_ID_V_VP8\n");
+ if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader))
+ track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader);
+
+ /* create a bitmap info header struct for vp8 */
+ bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len);
+ bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len;
+ bih->biCompression = ME_FOURCC('v', 'p', '8', '0');
+ bih->biWidth = track->video_track->pixel_width;
+ bih->biHeight = track->video_track->pixel_height;
+ _x_bmiheader_le2me(bih);
+
+ /* add bih extra data */
+ memcpy(bih + 1, track->codec_private, track->codec_private_len);
+ free(track->codec_private);
+ track->codec_private = (uint8_t *)bih;
+ track->codec_private_len = bih->biSize;
+ track->buf_type = BUF_VIDEO_VP8;
+
+ init_codec = init_codec_video;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV10)) {
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV20)) {
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV30)) {
diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h
index 2fad31ce4..41b27fa3f 100644
--- a/src/demuxers/matroska.h
+++ b/src/demuxers/matroska.h
@@ -314,6 +314,7 @@ struct matroska_track_s {
#define MATROSKA_CODEC_ID_V_REAL_RV40 "V_REAL/RV40"
#define MATROSKA_CODEC_ID_V_MJPEG "V_MJPEG"
#define MATROSKA_CODEC_ID_V_THEORA "V_THEORA"
+#define MATROSKA_CODEC_ID_V_VP8 "V_VP8"
#define MATROSKA_CODEC_ID_A_MPEG1_L1 "A_MPEG/L1"
#define MATROSKA_CODEC_ID_A_MPEG1_L2 "A_MPEG/L2"
diff --git a/src/spu_dec/spuhdmv_decoder.c b/src/spu_dec/spuhdmv_decoder.c
index 93e232678..0d93f919e 100644
--- a/src/spu_dec/spuhdmv_decoder.c
+++ b/src/spu_dec/spuhdmv_decoder.c
@@ -38,9 +38,22 @@
#include <xine/video_overlay.h>
#define XINE_HDMV_TRACE(x...) printf(x)
-/*#define TRACE(x...) */
+/*#define XINE_HDMV_TRACE(x...) */
#define XINE_HDMV_ERROR(x...) fprintf(stderr, "spuhdmv: " x)
-/*#define ERROR(x...) lprintf(x) */
+/*#define XINE_HDMV_ERROR(x...) lprintf(x) */
+
+#ifndef MAX
+# define MAX(a,b) (a>b)?(a):(b)
+#endif
+
+enum {
+ SEGTYPE_PALETTE = 0x14,
+ SEGTYPE_OBJECT = 0x15,
+ SEGTYPE_PRESENTATION_SEGMENT = 0x16,
+ SEGTYPE_WINDOW_DEFINITION = 0x17,
+ SEGTYPE_INTERACTIVE = 0x18,
+ SEGTYPE_END_OF_DISPLAY = 0x80,
+} eSegmentType;
/*
* cached palette (xine-lib format)
@@ -64,15 +77,16 @@ struct subtitle_object_s {
uint16_t xpos, ypos;
uint16_t width, height;
+ /* xine format */
rle_elem_t *rle;
unsigned int 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
+ /* HDMV format (used when object does not fit to single segment) */
+ uint32_t data_len; /* size of complete object */
+ uint8_t *raw_data; /* partial RLE data in HDMV format */
+ size_t raw_data_len; /* bytes buffered */
+ size_t raw_data_size; /* allocated size */
subtitle_object_t *next;
@@ -100,7 +114,7 @@ struct window_def_s {
typedef struct composition_object_s composition_object_t;
struct composition_object_s {
uint8_t window_id_ref;
- uint8_t object_id_ref;
+ uint16_t object_id_ref;
uint16_t xpos, ypos;
@@ -141,27 +155,27 @@ struct presentation_segment_s {
*/
#define LIST_REPLACE(list, obj, FREE_FUNC) \
- do { \
- unsigned int 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); \
- } \
+ do { \
+ unsigned int 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) { \
+ while (list) { \
void *tmp = (void*)list; \
- list = list->next; \
+ list = list->next; \
FREE_FUNC(tmp); \
}
@@ -169,6 +183,7 @@ static void free_subtitle_object(void *ptr)
{
if (ptr) {
free(((subtitle_object_t*)ptr)->rle);
+ free(((subtitle_object_t*)ptr)->raw_data);
free(ptr);
}
}
@@ -242,8 +257,8 @@ static void segbuf_parse_segment_header(segment_buffer_t *buf)
buf->error = 0;
if ( buf->segment_type < 0x14 ||
- ( buf->segment_type > 0x18 &&
- buf->segment_type != 0x80)) {
+ ( buf->segment_type > 0x18 &&
+ buf->segment_type != 0x80)) {
XINE_HDMV_ERROR("unknown segment type, resetting\n");
segbuf_reset(buf);
}
@@ -271,7 +286,7 @@ static void segbuf_fill(segment_buffer_t *buf, uint8_t *data, size_t len)
static int segbuf_segment_complete(segment_buffer_t *buf)
{
- return (buf->segment_len >= 0) && (buf->len >= buf->segment_len + 3);
+ return (buf->segment_len >= 0) && (buf->len >= (unsigned)buf->segment_len + 3);
}
static void segbuf_skip_segment(segment_buffer_t *buf)
@@ -286,7 +301,7 @@ static void segbuf_skip_segment(segment_buffer_t *buf)
XINE_HDMV_TRACE(" skip_segment: %zd bytes left\n", buf->len);
} else {
XINE_HDMV_ERROR(" skip_segment: ERROR - %zd bytes queued, %d required\n",
- buf->len, buf->segment_len);
+ buf->len, buf->segment_len);
segbuf_reset (buf);
}
}
@@ -311,7 +326,7 @@ static uint8_t segbuf_get_u8(segment_buffer_t *buf)
{
if (!(buf->error = ++buf->segment_data > buf->segment_end))
return buf->segment_data[-1];
- XINE_HDMV_ERROR("segbuf_get_u8: read failed (end of segment reached) !");
+ XINE_HDMV_ERROR("segbuf_get_u8: read failed (end of segment reached) !\n");
return 0;
}
@@ -325,19 +340,6 @@ static uint32_t segbuf_get_u24(segment_buffer_t *buf)
return (segbuf_get_u8(buf) << 16) | (segbuf_get_u8(buf) << 8) | segbuf_get_u8(buf);
}
-static uint8_t *segbuf_get_string(segment_buffer_t *buf, size_t len)
-{
- if (len > 0) {
- uint8_t *val = buf->segment_data;
- buf->segment_data += len;
- if (buf->segment_data <= buf->segment_end)
- return val;
- }
- XINE_HDMV_ERROR("segbuf_get_string(%zd): read failed (end of segment reached) !", len);
- buf->error = 1;
- return NULL;
-}
-
/*
* decode segments
*/
@@ -349,18 +351,18 @@ static subtitle_clut_t *segbuf_decode_palette(segment_buffer_t *buf)
size_t len = segbuf_data_length(buf);
size_t entries = len / 5;
- int i;
+ size_t i;
if (buf->error)
return NULL;
if (len % 5) {
XINE_HDMV_ERROR(" decode_palette: segment size error (%zd ; expected %zd for %zd entries)\n",
- len, (5 * entries), entries);
+ len, (5 * entries), entries);
return NULL;
}
XINE_HDMV_TRACE("decode_palette: %zd items (id %d, version %d)\n",
- entries, palette_id, palette_version_number);
+ entries, palette_id, palette_version_number);
/* convert to xine-lib clut */
subtitle_clut_t *clut = calloc(1, sizeof(subtitle_clut_t));
@@ -401,17 +403,17 @@ static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj)
} else {
byte = segbuf_get_u8 (buf);
if (!(byte & 0x80)) {
- rlep->color = 0;
- if (!(byte & 0x40))
- rlep->len = byte & 0x3f;
- else
- rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
+ rlep->color = 0;
+ if (!(byte & 0x40))
+ rlep->len = byte & 0x3f;
+ else
+ rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
} else {
- if (!(byte & 0x40))
- rlep->len = byte & 0x3f;
- else
- rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
- rlep->color = segbuf_get_u8 (buf);
+ if (!(byte & 0x40))
+ rlep->len = byte & 0x3f;
+ else
+ rlep->len = ((byte & 0x3f) << 8) | segbuf_get_u8 (buf);
+ rlep->color = segbuf_get_u8 (buf);
}
}
@@ -423,10 +425,10 @@ static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj)
} else {
/* end of line marker (00 00) */
if (x < obj->width) {
- rlep->len = obj->width - x;
- rlep->color = 0xff;
- rlep++;
- obj->num_rle ++;
+ rlep->len = obj->width - x;
+ rlep->color = 0xff;
+ rlep++;
+ obj->num_rle ++;
}
x = 0;
y++;
@@ -443,42 +445,104 @@ static int segbuf_decode_rle(segment_buffer_t *buf, subtitle_object_t *obj)
return buf->error;
}
-static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf)
+static subtitle_object_t *segbuf_decode_object(segment_buffer_t *buf, subtitle_object_t *objects)
{
- uint8_t object_id = segbuf_get_u16(buf);
+ uint16_t object_id = segbuf_get_u16(buf);
uint8_t version = segbuf_get_u8 (buf);
uint8_t seq_desc = segbuf_get_u8 (buf);
XINE_HDMV_TRACE(" decode_object: object_id %d, version %d, seq 0x%x\n",
- object_id, version, seq_desc);
-
- //LIST_FIND();
- subtitle_object_t *obj = calloc(1, sizeof(subtitle_object_t));
- obj->id = object_id;
+ object_id, version, seq_desc);
if (seq_desc & 0x80) {
+ /* new object (first-in-sequence flag set) */
+
+ subtitle_object_t *obj = calloc(1, sizeof(subtitle_object_t));
- uint32_t data_len = segbuf_get_u24(buf);
+ obj->id = object_id;
+ obj->data_len = segbuf_get_u24(buf);
obj->width = segbuf_get_u16(buf);
obj->height = segbuf_get_u16(buf);
- XINE_HDMV_TRACE(" object length %d bytes, size %dx%d\n", data_len, obj->width, obj->height);
+ if (buf->error) {
+ XINE_HDMV_TRACE(" decode error at object header\n");
+ free_subtitle_object(obj);
+ return NULL;
+ }
+
+ obj->data_len -= 4; /* width, height parsed */
+
+ XINE_HDMV_TRACE(" object length %d bytes, size %dx%d\n", obj->data_len, obj->width, obj->height);
+
+ if (obj->data_len > segbuf_data_length(buf)) {
+ XINE_HDMV_TRACE(" object length %d bytes, have only %zd bytes -> missing %d bytes\n",
+ obj->data_len, segbuf_data_length(buf), obj->data_len - (int)segbuf_data_length(buf));
+
+ if (obj->raw_data)
+ free(obj->raw_data);
+
+ /* store partial RLE data in HDMV format */
+ obj->raw_data_len = segbuf_data_length(buf);
+ obj->raw_data_size = MAX(obj->data_len, obj->raw_data_len);
+ obj->raw_data = malloc(obj->raw_data_size);
+ memcpy(obj->raw_data, buf->segment_data, obj->raw_data_len);
+
+ return obj;
+ }
segbuf_decode_rle (buf, obj);
if (buf->error) {
+ XINE_HDMV_TRACE(" decode error at RLE data\n");
free_subtitle_object(obj);
return NULL;
}
- } else {
- XINE_HDMV_ERROR(" TODO: APPEND RLE, length %d bytes\n", buf->segment_len - 4);
- /* TODO */
- free_subtitle_object(obj);
+ return obj;
+ }
+
+ /* not first-of-sequence --> append data to already existing objct */
+
+ /* search for object */
+ while (objects && objects->id != object_id)
+ objects = objects->next;
+
+ if (!objects) {
+ XINE_HDMV_TRACE(" object not found from list, discarding segment\n");
return NULL;
}
- return obj;
+ /* store partial RLE data in HDMV format */
+ if (objects->raw_data_size < objects->raw_data_len + segbuf_data_length(buf)) {
+ XINE_HDMV_ERROR("object larger than object size !\n");
+ return NULL;
+ }
+ memcpy(objects->raw_data + objects->raw_data_len, buf->segment_data, segbuf_data_length(buf));
+ objects->raw_data_len += segbuf_data_length(buf);
+
+ /* if complete, decode RLE data */
+ if (objects->raw_data_len >= objects->data_len) {
+ /* create dummy buffer for segbuf_decode_rle */
+ segment_buffer_t tmpbuf = {
+ .segment_data = objects->raw_data,
+ .segment_end = objects->raw_data + objects->raw_data_len,
+ };
+
+ /* decode RLE data */
+ segbuf_decode_rle (&tmpbuf, objects);
+
+ if (tmpbuf.error) {
+ XINE_HDMV_TRACE(" error decoding multi-segment object\n");
+ }
+
+ /* free decode buffer */
+ free(objects->raw_data);
+ objects->raw_data = NULL;
+ objects->raw_data_len = 0;
+ objects->raw_data_size = 0;
+ }
+
+ return NULL;
}
static window_def_t *segbuf_decode_window_definition(segment_buffer_t *buf)
@@ -493,7 +557,7 @@ static window_def_t *segbuf_decode_window_definition(segment_buffer_t *buf)
wnd->height = segbuf_get_u16 (buf);
XINE_HDMV_TRACE(" window: [%02x %d] %d,%d %dx%d\n", a,
- wnd->id, wnd->xpos, wnd->ypos, wnd->width, wnd->height);
+ wnd->id, wnd->xpos, wnd->ypos, wnd->width, wnd->height);
if (buf->error) {
free(wnd);
@@ -510,13 +574,14 @@ static int segbuf_decode_video_descriptor(segment_buffer_t *buf)
uint8_t frame_rate = segbuf_get_u8 (buf);
XINE_HDMV_TRACE(" video_descriptor: %dx%d fps %d\n", width, height, frame_rate);
+
return buf->error;
}
static int segbuf_decode_composition_descriptor(segment_buffer_t *buf, composition_descriptor_t *descr)
{
descr->number = segbuf_get_u16(buf);
- descr->state = segbuf_get_u8 (buf);
+ descr->state = segbuf_get_u8 (buf) & 0xc0;
XINE_HDMV_TRACE(" composition_descriptor: number %d, state %d\n", descr->number, descr->state);
return buf->error;
@@ -548,8 +613,8 @@ static composition_object_t *segbuf_decode_composition_object(segment_buffer_t *
}
XINE_HDMV_TRACE(" composition_object: id: %d, win: %d, position %d,%d crop %d forced %d\n",
- cobj->object_id_ref, cobj->window_id_ref, cobj->xpos, cobj->ypos,
- cobj->cropped_flag, cobj->forced_flag);
+ cobj->object_id_ref, cobj->window_id_ref, cobj->xpos, cobj->ypos,
+ cobj->cropped_flag, cobj->forced_flag);
return cobj;
}
@@ -567,7 +632,7 @@ static presentation_segment_t *segbuf_decode_presentation_segment(segment_buffer
seg->object_number = segbuf_get_u8 (buf);
XINE_HDMV_TRACE(" presentation_segment: object_number %d, palette %d\n",
- seg->object_number, seg->palette_id_ref);
+ seg->object_number, seg->palette_id_ref);
for (index = 0; index < seg->object_number; index++) {
composition_object_t *cobj = segbuf_decode_composition_object (buf);
@@ -620,6 +685,14 @@ typedef struct spuhdmv_decoder_s {
} spuhdmv_decoder_t;
+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 int decode_palette(spuhdmv_decoder_t *this)
{
/* decode */
@@ -635,7 +708,7 @@ static int decode_palette(spuhdmv_decoder_t *this)
static int decode_object(spuhdmv_decoder_t *this)
{
/* decode */
- subtitle_object_t *obj = segbuf_decode_object(this->buf);
+ subtitle_object_t *obj = segbuf_decode_object(this->buf, this->objects);
if (!obj)
return 1;
@@ -665,6 +738,11 @@ static int decode_presentation_segment(spuhdmv_decoder_t *this)
seg->pts = this->pts;
+ /* epoch start or acquistion point -> drop cached objects */
+ if (seg->comp_descr.state) {
+ free_objs(this);
+ }
+
/* replace */
if (this->segments)
LIST_DESTROY(this->segments, free_presentation_segment);
@@ -674,7 +752,7 @@ static int decode_presentation_segment(spuhdmv_decoder_t *this)
}
static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, unsigned int palette_id_ref,
- int overlay_index, int64_t pts, int force_update)
+ 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;
@@ -698,6 +776,10 @@ static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uns
XINE_HDMV_TRACE(" show_overlay: object %d not found !\n", cobj->object_id_ref);
return -1;
}
+ if (!obj->rle) {
+ XINE_HDMV_TRACE(" show_overlay: object %d RLE data not decoded !\n", cobj->object_id_ref);
+ return -1;
+ }
/* find window */
window_def_t *wnd = this->windows;
@@ -738,7 +820,7 @@ static int show_overlay(spuhdmv_decoder_t *this, composition_object_t *cobj, uns
overlay.hili_right = -1;
XINE_HDMV_TRACE(" -> overlay: %d,%d %dx%d\n",
- overlay.x, overlay.y, overlay.width, overlay.height);
+ overlay.x, overlay.y, overlay.width, overlay.height);
/* set timings */
@@ -797,7 +879,7 @@ static void update_overlays(spuhdmv_decoder_t *this)
while (pseg) {
- if (!pseg->comp_descr.state) {
+ if (!pseg->object_number) {
/* HIDE */
if (!pseg->shown)
@@ -825,46 +907,40 @@ static void update_overlays(spuhdmv_decoder_t *this)
}
}
-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)
{
- XINE_HDMV_TRACE("*** new segment, pts %010ld: 0x%02x (%8d bytes)",
- this->pts, this->buf->segment_type, this->buf->segment_len);
+ XINE_HDMV_TRACE("*** new segment, pts %010"PRId64": 0x%02x (%8d bytes)\n",
+ this->pts, this->buf->segment_type, this->buf->segment_len);
- switch (this->buf->segment_type) {
- case 0x14:
+ switch (segbuf_segment_type(this->buf)) {
+ case SEGTYPE_PALETTE:
XINE_HDMV_TRACE(" segment: PALETTE\n");
decode_palette(this);
break;
- case 0x15:
+ case SEGTYPE_OBJECT:
XINE_HDMV_TRACE(" segment: OBJECT\n");
decode_object(this);
break;
- case 0x16:
+ case SEGTYPE_PRESENTATION_SEGMENT:
XINE_HDMV_TRACE(" segment: PRESENTATION SEGMENT\n");
decode_presentation_segment(this);
break;
- case 0x17:
+ case SEGTYPE_WINDOW_DEFINITION:
XINE_HDMV_TRACE(" segment: WINDOW DEFINITION\n");
decode_window_definition(this);
break;
- case 0x18:
+ case SEGTYPE_INTERACTIVE:
XINE_HDMV_TRACE(" segment: INTERACTIVE\n");
break;
- case 0x80:
+ case SEGTYPE_END_OF_DISPLAY:
XINE_HDMV_TRACE(" segment: END OF DISPLAY\n");
+#if 0
/* drop all cached objects */
free_objs(this);
+#endif
break;
default:
- XINE_HDMV_ERROR(" segment type 0x%x unknown, skipping\n", this->buf->segment_type);
+ XINE_HDMV_ERROR(" segment type 0x%x unknown, skipping\n", segbuf_segment_type(this->buf));
break;
}
if (this->buf->error) {
diff --git a/src/xine-engine/audio_decoder.c b/src/xine-engine/audio_decoder.c
index e2d0acd04..e36f576bd 100644
--- a/src/xine-engine/audio_decoder.c
+++ b/src/xine-engine/audio_decoder.c
@@ -283,6 +283,9 @@ static void *audio_decoder_loop (void *stream_gen) {
}
stream->audio_track_map[i] = buf->type;
stream->audio_track_map_entries++;
+ /* implicit channel change - reopen decoder below */
+ if ((i == 0) && (audio_channel_user == -1) && (stream->audio_channel_auto < 0))
+ stream->audio_decoder_streamtype = -1;
ui_event.type = XINE_EVENT_UI_CHANNELS_CHANGED;
ui_event.data_length = 0;
diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c
index dc8550ca1..6f45672ee 100644
--- a/src/xine-engine/buffer_types.c
+++ b/src/xine-engine/buffer_types.c
@@ -791,6 +791,14 @@ static const video_db_t video_db[] = {
BUF_VIDEO_SNOW,
"Snow"
},
+{
+ {
+ ME_FOURCC('V','P','8','0'),
+ 0
+ },
+ BUF_VIDEO_VP8,
+ "On2 VP8"
+},
{ { 0 }, 0, "last entry" }
};
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index f348da3f5..cc428137e 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -880,25 +880,28 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
* check for first frame after seek and mark it
*/
img->is_first = 0;
- pthread_mutex_lock(&this->streams_lock);
- for (ite = xine_list_front(this->streams); ite;
- ite = xine_list_next(this->streams, ite)) {
- stream = xine_list_get_value(this->streams, ite);
- if (stream == XINE_ANON_STREAM) continue;
- pthread_mutex_lock (&stream->first_frame_lock);
- if (stream->first_frame_flag == 2) {
- if (this->grab_only) {
- stream->first_frame_flag = 0;
- pthread_cond_broadcast(&stream->first_frame_reached);
- } else
- stream->first_frame_flag = 1;
- img->is_first = FIRST_FRAME_MAX_POLL;
-
- lprintf ("get_next_video_frame first_frame_reached\n");
+ /* avoid a complex deadlock situation caused by net_buf_control */
+ if (!pthread_mutex_trylock(&this->streams_lock)) {
+ for (ite = xine_list_front(this->streams); ite;
+ ite = xine_list_next(this->streams, ite)) {
+ stream = xine_list_get_value(this->streams, ite);
+ if (stream == XINE_ANON_STREAM) continue;
+ pthread_mutex_lock (&stream->first_frame_lock);
+ if (stream->first_frame_flag == 2) {
+ if (this->grab_only) {
+ stream->first_frame_flag = 0;
+ pthread_cond_broadcast(&stream->first_frame_reached);
+ } else {
+ stream->first_frame_flag = 1;
+ }
+ img->is_first = FIRST_FRAME_MAX_POLL;
+
+ lprintf ("get_next_video_frame first_frame_reached\n");
+ }
+ pthread_mutex_unlock (&stream->first_frame_lock);
}
- pthread_mutex_unlock (&stream->first_frame_lock);
+ pthread_mutex_unlock(&this->streams_lock);
}
- pthread_mutex_unlock(&this->streams_lock);
if (!img_already_locked)
vo_frame_inc_lock( img );
@@ -1110,7 +1113,7 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) {
while (img) {
- if (img->is_first) {
+ if (img->is_first > 0) {
lprintf("expire_frames: first_frame !\n");
/*
@@ -1127,6 +1130,8 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) {
img->vpts = cur_vpts + FIRST_FRAME_POLL_DELAY;
}
img->is_first--;
+ /* make sure to wake up xine_play even if this first frame gets discarded */
+ if (img->is_first == 0) img->is_first = -1;
break;
}
@@ -1156,6 +1161,24 @@ static void expire_frames (vos_t *this, int64_t cur_vpts) {
pthread_mutex_lock( &img->stream->current_extra_info_lock );
_x_extra_info_merge( img->stream->current_extra_info, img->extra_info );
pthread_mutex_unlock( &img->stream->current_extra_info_lock );
+ /* wake up xine_play now if we just discarded first frame */
+ if (img->is_first != 0) {
+ xine_list_iterator_t ite;
+ pthread_mutex_lock (&this->streams_lock);
+ for (ite = xine_list_front(this->streams); ite;
+ ite = xine_list_next(this->streams, ite)) {
+ xine_stream_t *stream = xine_list_get_value (this->streams, ite);
+ if (stream == XINE_ANON_STREAM) continue;
+ pthread_mutex_lock (&stream->first_frame_lock);
+ if (stream->first_frame_flag) {
+ stream->first_frame_flag = 0;
+ pthread_cond_broadcast (&stream->first_frame_reached);
+ }
+ pthread_mutex_unlock (&stream->first_frame_lock);
+ }
+ pthread_mutex_unlock(&this->streams_lock);
+ xine_log (this->xine, XINE_LOG_MSG, _("video_out: just discarded first frame after seek\n"));
+ }
}
/* when flushing frames, keep the first one as backup */