diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2011-08-23 20:18:22 +0100 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2011-08-23 20:18:22 +0100 |
commit | b097a80fb2d9100e02f2fdaf62fe3d408f73763f (patch) | |
tree | 930fda0d620d73f453e7be7eb51aad28de3395cf | |
parent | 53ec0b8ab9e7076d84221bbd5ea84978239a1afc (diff) | |
parent | edb68926aced0739f3e62ea2501bc32326c02f86 (diff) | |
download | xine-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.h | 1 | ||||
-rw-r--r-- | src/audio_dec/xine_lpcm_decoder.c | 8 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_audio_decoder.c | 36 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_video_decoder.c | 6 | ||||
-rw-r--r-- | src/combined/ffmpeg/xine_video.list | 3 | ||||
-rw-r--r-- | src/demuxers/demux_matroska.c | 23 | ||||
-rw-r--r-- | src/demuxers/matroska.h | 1 | ||||
-rw-r--r-- | src/spu_dec/spuhdmv_decoder.c | 278 | ||||
-rw-r--r-- | src/xine-engine/audio_decoder.c | 3 | ||||
-rw-r--r-- | src/xine-engine/buffer_types.c | 8 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 59 |
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 */ |