diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2004-07-14 01:18:47 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2004-07-14 01:18:47 +0000 |
commit | 46df82be838571af99d0266f773b5fb274a924b5 (patch) | |
tree | 77a5cc43936b4ec376b4be7b48297be3858e1db3 | |
parent | bd4c703f8be11c6183229c472eeab239325aea58 (diff) | |
download | xine-lib-46df82be838571af99d0266f773b5fb274a924b5.tar.gz xine-lib-46df82be838571af99d0266f773b5fb274a924b5.tar.bz2 |
Moritz patch for matroska vobsub support
align vobsub to bottom in libspudec
CVS patchset: 6791
CVS date: 2004/07/14 01:18:47
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | src/demuxers/demux_matroska.c | 257 | ||||
-rw-r--r-- | src/demuxers/matroska.h | 16 | ||||
-rw-r--r-- | src/libspudec/spu.c | 18 | ||||
-rw-r--r-- | src/libspudec/spu.h | 3 | ||||
-rw-r--r-- | src/libspudec/xine_decoder.c | 9 | ||||
-rw-r--r-- | src/xine-engine/buffer.h | 4 |
7 files changed, 302 insertions, 9 deletions
@@ -5,8 +5,10 @@ xine-lib (1-rc6) might lead to undefined behaviour; calling XInitThreads() is entirely the frontend's job * include goom2k4-dev15 + * make sure the streams are played till their very end * support for Annodex files - + * VobSub-in-Matroska support + xine-lib (1-rc5) * add support for ejecting removable media on Solaris * fix stuttering playback of some realmedia streams diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index b8442341c..d281590be 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_matroska.c,v 1.28 2004/06/13 21:28:53 miguelfreitas Exp $ + * $Id: demux_matroska.c,v 1.29 2004/07/14 01:18:48 miguelfreitas Exp $ * * demultiplexer for matroska streams * @@ -32,11 +32,13 @@ #include "config.h" #endif +#include <ctype.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <string.h> #include <stdlib.h> +#include <zlib.h> #define LOG_MODULE "demux_matroska" #define LOG_VERBOSE @@ -58,6 +60,13 @@ #define WRAP_THRESHOLD 90000 +#if !defined(MIN) +#define MIN(a, b) ((a)<(b)?(a):(b)) +#endif +#if !defined(MAX) +#define MAX(a, b) ((a)>(b)?(a):(b)) +#endif + typedef struct { int track_num; off_t *pos; @@ -508,6 +517,166 @@ static void init_codec_vorbis(demux_matroska_t *this, matroska_track_t *track) { } } + +static int vobsub_parse_size(matroska_track_t *t, const char *start) { + if (sscanf(&start[6], "%dx%d", &t->sub_track->width, + &t->sub_track->height) == 2) { + lprintf("VobSub size: %ux%u\n", t->sub_track->width, t->sub_track->height); + return 1; + } + return 0; +} + +static int vobsub_parse_palette(matroska_track_t *t, const char *start) { + int i, r, g, b, y, u, v, tmp; + + start += 8; + while (isspace(*start)) + start++; + for (i = 0; i < 16; i++) { + if (sscanf(start, "%06x", &tmp) != 1) + break; + r = tmp >> 16 & 0xff; + g = tmp >> 8 & 0xff; + b = tmp & 0xff; + y = MIN(MAX((int)(0.1494 * r + 0.6061 * g + 0.2445 * b), 0), 0xff); + u = MIN(MAX((int)(0.6066 * r - 0.4322 * g - 0.1744 * b) + 128, 0), 0xff); + v = MIN(MAX((int)(-0.08435 * r - 0.3422 * g + 0.4266 * b) + 128, 0), 0xff); + t->sub_track->palette[i] = y << 16 | u << 8 | v; + start += 6; + while ((*start == ',') || isspace(*start)) + start++; + } + if (i == 16) { + lprintf("VobSub palette: %06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x,%06x," + "%06x,%06x,%06x,%06x,%06x,%06x,%06x\n", t->sub_track->palette[0], + t->sub_track->palette[1], t->sub_track->palette[2], + t->sub_track->palette[3], t->sub_track->palette[4], + t->sub_track->palette[5], t->sub_track->palette[6], + t->sub_track->palette[7], t->sub_track->palette[8], + t->sub_track->palette[9], t->sub_track->palette[10], + t->sub_track->palette[11], t->sub_track->palette[12], + t->sub_track->palette[13], t->sub_track->palette[14], + t->sub_track->palette[15]); + return 2; + } + return 0; +} + +static int vobsub_parse_custom_colors(matroska_track_t *t, const char *start) { + int use_custom_colors, i; + + start += 14; + while (isspace(*start)) + start++; + use_custom_colors = 0; + if (!strncasecmp(start, "ON", 2) || (*start == '1')) + use_custom_colors = 1; + else if (!strncasecmp(start, "OFF", 3) || (*start == '0')) + use_custom_colors = 0; + lprintf("VobSub custom colors: %s\n", use_custom_colors ? "ON" : "OFF"); + if ((start = strstr(start, "colors:")) != NULL) { + start += 7; + while (isspace(*start)) + start++; + for (i = 0; i < 4; i++) { + if (sscanf(start, "%06x", &t->sub_track->colors[i]) != 1) + break; + start += 6; + while ((*start == ',') || isspace(*start)) + start++; + } + if (i == 4) { + t->sub_track->custom_colors = 4; + lprintf("VobSub colors: %06x,%06x,%06x,%06x\n", t->sub_track->colors[0], + t->sub_track->colors[1], t->sub_track->colors[2], + t->sub_track->colors[3]); + } + } + if (!use_custom_colors) + t->sub_track->custom_colors = 0; + return 4; +} + +static int vobsub_parse_forced_subs(matroska_track_t *t, const char *start) { + start += 12; + while (isspace(*start)) + start++; + if (!strncasecmp(start, "on", 2) || (*start == '1')) + t->sub_track->forced_subs_only = 1; + else if (!strncasecmp(start, "off", 3) || (*start == '0')) + t->sub_track->forced_subs_only = 0; + else + return 0; + lprintf("VobSub forced subs: %d\n", t->sub_track->forced_subs_only); + return 8; +} + +static void init_codec_vobsub(demux_matroska_t *this, + matroska_track_t *track) { + int things_found, last; + char *buf, *pos, *start; + buf_element_t *buf_el; + + lprintf("init_codec_vobsub for %d\n", track->track_num); + + if ((track->codec_private == NULL) || (track->codec_private_len == 0)) + return; + + track->sub_track = calloc(1, sizeof(matroska_sub_track_t)); + if (track->sub_track == NULL) + return; + things_found = 0; + buf = (char *)malloc(track->codec_private_len + 1); + if (buf == NULL) + return; + xine_fast_memcpy(buf, track->codec_private, track->codec_private_len); + buf[track->codec_private_len] = 0; + track->sub_track->type = 'v'; + + pos = buf; + start = buf; + last = 0; + + do { + if ((*pos == 0) || (*pos == '\r') || (*pos == '\n')) { + if (*pos == 0) + last = 1; + *pos = 0; + + if (!strncasecmp(start, "size: ", 6)) + things_found |= vobsub_parse_size(track, start); + else if (!strncasecmp(start, "palette:", 8)) + things_found |= vobsub_parse_palette(track, start); + else if (!strncasecmp(start, "custom colors:", 14)) + things_found |= vobsub_parse_custom_colors(track, start); + else if (!strncasecmp(start, "forced subs:", 12)) + things_found |= vobsub_parse_forced_subs(track, start); + + if (last) + break; + do { + pos++; + } while ((*pos == '\r') || (*pos == '\n')); + start = pos; + } else + pos++; + } while (!last && (*start != 0)); + + free(buf); + + if ((things_found & 2) == 2) { + buf_el = track->fifo->buffer_pool_alloc(track->fifo); + xine_fast_memcpy(buf_el->content, track->sub_track->palette, + 16 * sizeof(uint32_t)); + buf_el->type = BUF_SPU_DVD; + buf_el->decoder_flags |= BUF_FLAG_SPECIAL; + buf_el->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE; + buf_el->decoder_info[2] = SPU_DVD_SUBTYPE_CLUT; + track->fifo->put(track->fifo, buf_el); + } +} + static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track, int decoder_flags, uint8_t *data, int data_len, @@ -665,6 +834,85 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track, } +/* Note: This function assumes that the VobSub track is compressed with zlib. + * This is not necessarily true - or not enough. The Matroska 'content + * encoding' elements allow for a layer of changes applied to the contents, + * e.g. compression or encryption. Anyway, only zlib compression is used + * at the moment, and everyone compresses the VobSubs. + */ +static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, + int decoder_flags, + uint8_t *data, int data_len, + int64_t data_pts, int data_duration, + int input_normpos, int input_time) { + demux_matroska_t *this = (demux_matroska_t *) this_gen; + buf_element_t *buf; + z_stream zstream; + uint8_t *dest; + int old_data_len, result; + + old_data_len = data_len; + zstream.zalloc = (alloc_func) 0; + zstream.zfree = (free_func) 0; + zstream.opaque = (voidpf) 0; + if (inflateInit (&zstream) != Z_OK) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: VobSub: zlib inflateInit failed.\n"); + return; + } + zstream.next_in = (Bytef *)data; + zstream.avail_in = data_len; + + dest = (uint8_t *)malloc(data_len); + zstream.avail_out = data_len; + do { + data_len += 4000; + dest = (uint8_t *)realloc(dest, data_len); + zstream.next_out = (Bytef *)(dest + zstream.total_out); + result = inflate (&zstream, Z_NO_FLUSH); + if ((result != Z_OK) && (result != Z_STREAM_END)) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: VobSub: zlib decompression failed.\n"); + free(dest); + inflateEnd(&zstream); + return; + } + zstream.avail_out += 4000; + } while ((zstream.avail_out == 4000) && + (zstream.avail_in != 0) && (result != Z_STREAM_END)); + + data_len = zstream.total_out; + inflateEnd(&zstream); + + lprintf("VobSub: decompression for track %d from %d to %d\n", + (int)track->track_num, old_data_len, data_len); + + buf = track->fifo->buffer_pool_alloc(track->fifo); + + buf->size = data_len; + if (buf->max_size >= buf->size) { + buf->decoder_flags = decoder_flags | BUF_FLAG_SPECIAL; + buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE; + buf->decoder_info[2] = SPU_DVD_SUBTYPE_VOBSUB_PACKAGE; + buf->type = track->buf_type; + + xine_fast_memcpy(buf->content, dest, data_len); + + buf->extra_info->input_normpos = input_normpos; + buf->extra_info->input_time = input_time; + + buf->pts = data_pts; + track->fifo->put(track->fifo, buf); + + } else { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: VobSub: data length is greater than fifo buffer length\n"); + buf->free_buffer(buf); + } + + free(dest); +} + static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { ebml_parser_t *ebml = this->ebml; int next_level = 3; @@ -888,6 +1136,11 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { lprintf("MATROSKA_CODEC_ID_S_TEXT_USF\n"); track->buf_type = BUF_SPU_OGM; track->handle_content = handle_sub_utf8; + } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_VOBSUB)) { + lprintf("MATROSKA_CODEC_ID_S_VOBSUB\n"); + track->buf_type = BUF_SPU_DVD; + track->handle_content = handle_vobsub; + init_codec = init_codec_vobsub; } else { lprintf("unknown codec\n"); } @@ -2093,6 +2346,8 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) { free (track->video_track); if (track->audio_track) free (track->audio_track); + if (track->sub_track) + free (track->sub_track); free (track); } diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 2c887f152..a203b2e2f 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: matroska.h,v 1.7 2004/06/13 21:28:55 miguelfreitas Exp $ + * $Id: matroska.h,v 1.8 2004/07/14 01:18:48 miguelfreitas Exp $ * */ #ifndef MATROSKA_H @@ -201,6 +201,18 @@ typedef struct { int bits_per_sample; } matroska_audio_track_t; +typedef struct { + char type; + + /* The rest is used for VobSubs (type = 'v'). */ + int width; + int height; + uint32_t palette[16]; + int custom_colors; + uint32_t colors[4]; + int forced_subs_only; +} matroska_sub_track_t; + typedef struct matroska_track_s matroska_track_t; struct matroska_track_s { int track_num; @@ -218,6 +230,7 @@ struct matroska_track_s { matroska_video_track_t *video_track; matroska_audio_track_t *audio_track; + matroska_sub_track_t *sub_track; int64_t last_pts; @@ -275,6 +288,7 @@ struct matroska_track_s { #define MATROSKA_CODEC_ID_S_UTF8 "S_UTF8" /* deprecated */ #define MATROSKA_CODEC_ID_S_SSA "S_SSA" /* deprecated */ #define MATROSKA_CODEC_ID_S_ASS "S_ASS" /* deprecated */ +#define MATROSKA_CODEC_ID_S_VOBSUB "S_VOBSUB" /* block lacing */ #define MATROSKA_NO_LACING 0x0 diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index 8d4bdcc5e..336837737 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -36,7 +36,7 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: spu.c,v 1.76 2004/06/26 13:49:54 mroi Exp $ + * $Id: spu.c,v 1.77 2004/07/14 01:18:48 miguelfreitas Exp $ * */ @@ -488,6 +488,22 @@ void spudec_process (spudec_decoder_t *this, int stream_id) { spudec_discover_clut(this->stream->xine, &this->state, &this->overlay); } + if (this->state.vobsub) { + int width, height; + int64_t duration; + + /* + * vobsubs are usually played with a scaled-down stream (not full DVD + * resolution), therefore we should try to realign it. + */ + + this->stream->video_out->status(this->stream->video_out, NULL, + &width, &height, &duration ); + + this->overlay.x = (width - this->overlay.width) / 2; + this->overlay.y = height - this->overlay.height; + } + /* Subtitle */ if( this->menu_handle < 0 ) { this->menu_handle = ovl_manager->get_handle(ovl_manager,1); diff --git a/src/libspudec/spu.h b/src/libspudec/spu.h index 6da793f1c..91f4f8ab6 100644 --- a/src/libspudec/spu.h +++ b/src/libspudec/spu.h @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: spu.h,v 1.26 2004/06/21 16:19:41 mroi Exp $ + * $Id: spu.h,v 1.27 2004/07/14 01:18:48 miguelfreitas Exp $ * * This file was originally part of the OMS program. * @@ -85,6 +85,7 @@ typedef struct { int32_t delay; /* Delay in 90Khz / 1000 */ int32_t need_clut; /* doesn't have the right clut yet */ int32_t cur_colors[4];/* current 4 colors been used */ + int32_t vobsub; /* vobsub must be aligned to bottom */ uint32_t clut[16]; } spudec_state_t; diff --git a/src/libspudec/xine_decoder.c b/src/libspudec/xine_decoder.c index 5fa10b944..985d3305d 100644 --- a/src/libspudec/xine_decoder.c +++ b/src/libspudec/xine_decoder.c @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: xine_decoder.c,v 1.107 2004/06/21 16:19:41 mroi Exp $ + * $Id: xine_decoder.c,v 1.108 2004/07/14 01:18:48 miguelfreitas Exp $ * * stuff needed to turn libspu into a xine decoder plugin */ @@ -108,7 +108,11 @@ static void spudec_decode_data (spu_decoder_t *this_gen, buf_element_t *buf) { spudec_decode_nav(this,buf); return; } - + + if ( buf->decoder_info[2] == SPU_DVD_SUBTYPE_VOBSUB_PACKAGE ) { + this->state.vobsub = 1; + } + /* check, if we need to process the next PCI from the list */ pthread_mutex_lock(&this->nav_pci_lock); spudec_update_nav(this); @@ -338,6 +342,7 @@ static spu_decoder_t *open_plugin (spu_decoder_class_t *class_gen, xine_stream_t /* FIXME:Do we really need a default clut? */ xine_fast_memcpy(this->state.clut, __default_clut, sizeof(this->state.clut)); this->state.need_clut = 1; + this->state.vobsub = 0; return &this->spu_decoder; } diff --git a/src/xine-engine/buffer.h b/src/xine-engine/buffer.h index a9239aaea..9295356b4 100644 --- a/src/xine-engine/buffer.h +++ b/src/xine-engine/buffer.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: buffer.h,v 1.139 2004/06/21 16:19:40 mroi Exp $ + * $Id: buffer.h,v 1.140 2004/07/14 01:18:47 miguelfreitas Exp $ * * * contents: @@ -442,7 +442,7 @@ struct buf_element_s { #define SPU_DVD_SUBTYPE_CLUT 1 #define SPU_DVD_SUBTYPE_PACKAGE 2 -/* FIXME: number 3 is unused */ +#define SPU_DVD_SUBTYPE_VOBSUB_PACKAGE 3 #define SPU_DVD_SUBTYPE_NAV 4 /* In a BUF_SPECIAL_SPU_DVB_DESCRIPTOR |