From: Miguel F. <mig...@us...> - 2004-07-14 01:18:57
|
Update of /cvsroot/xine/xine-lib/src/demuxers In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv4996/src/demuxers Modified Files: demux_matroska.c matroska.h Log Message: Moritz patch for matroska vobsub support align vobsub to bottom in libspudec Index: demux_matroska.c =================================================================== RCS file: /cvsroot/xine/xine-lib/src/demuxers/demux_matroska.c,v retrieving revision 1.28 retrieving revision 1.29 diff -u -r1.28 -r1.29 --- demux_matroska.c 13 Jun 2004 21:28:53 -0000 1.28 +++ demux_matroska.c 14 Jul 2004 01:18:48 -0000 1.29 @@ -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 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 @@ } +/* 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 @@ 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 @@ free (track->video_track); if (track->audio_track) free (track->audio_track); + if (track->sub_track) + free (track->sub_track); free (track); } Index: matroska.h =================================================================== RCS file: /cvsroot/xine/xine-lib/src/demuxers/matroska.h,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- matroska.h 13 Jun 2004 21:28:55 -0000 1.7 +++ matroska.h 14 Jul 2004 01:18:48 -0000 1.8 @@ -201,6 +201,18 @@ 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 @@ 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 @@ #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 |