summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-12-08 13:59:49 +0100
committerwm4 <wm4@nowhere>2012-12-11 00:37:54 +0100
commit5bf8706d1f6536cd89207b777161ab83195ddb20 (patch)
tree1e4ba07a00da6dcde3f8f308f2aa1128af56619e /sub
parentb3fb7c2cade9d70a4ca05821c87f68e941da6237 (diff)
downloadmpv-5bf8706d1f6536cd89207b777161ab83195ddb20.tar.bz2
mpv-5bf8706d1f6536cd89207b777161ab83195ddb20.tar.xz
sub: remove vobsub reader in favor of ffmpeg vobsub demuxer
ffmpeg recently added a demuxer that can read vobsubs (pairs of .sub and .idx files). Get rid of the internal vobsub reader, and use the ffmpeg demuxer instead. Sneak in an unrelated manpage change (autosub default).
Diffstat (limited to 'sub')
-rw-r--r--sub/find_subfiles.c53
-rw-r--r--sub/find_subfiles.h1
-rw-r--r--sub/spudec.c28
-rw-r--r--sub/vobsub.c980
-rw-r--r--sub/vobsub.h43
5 files changed, 29 insertions, 1076 deletions
diff --git a/sub/find_subfiles.c b/sub/find_subfiles.c
index 502fc911dc..95004b564f 100644
--- a/sub/find_subfiles.c
+++ b/sub/find_subfiles.c
@@ -87,7 +87,7 @@ static void append_dir_subtitles(struct MPOpts *opts,
struct bstr path, const char *fname,
int limit_fuzziness)
{
- char *sub_exts[] = {"utf", "utf8", "utf-8", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL};
+ char *sub_exts[] = {"utf", "utf8", "utf-8", "idx", "sub", "srt", "smi", "rt", "txt", "ssa", "aqt", "jss", "js", "ass", NULL};
void *tmpmem = talloc_new(NULL);
FILE *f;
assert(strlen(fname) < 1e6);
@@ -117,20 +117,6 @@ static void append_dir_subtitles(struct MPOpts *opts,
struct bstr tmp_fname_ext = get_ext(dename);
struct bstr tmp_fname_trim = bstr_strip(tmp_fname_noext);
- // If it's a .sub, check if there is a .idx with the same name. If
- // there is one, it's certainly a vobsub so we skip it.
- if (bstrcasecmp(tmp_fname_ext, bstr0("sub")) == 0) {
- char *idxname = talloc_asprintf(tmpmem2, "%.*s.idx",
- (int)tmp_fname_noext.len,
- de->d_name);
- char *idx = mp_path_join(tmpmem2, path, bstr0(idxname));
- f = fopen(idx, "rt");
- if (f) {
- fclose(f);
- goto next_sub;
- }
- }
-
// does it end with a subtitle extension?
#ifdef CONFIG_ICONV
#ifdef CONFIG_ENCA
@@ -183,7 +169,7 @@ static void append_dir_subtitles(struct MPOpts *opts,
if (prio) {
prio += prio;
#ifdef CONFIG_ICONV
- if (i < 3) // prefer UTF-8 coded
+ if (i < 4) // prefer UTF-8 coded, or idx over sub (vobsubs)
prio++;
#endif
char *subpath = mp_path_join(*slist, path, dename);
@@ -241,38 +227,3 @@ char **find_text_subtitles(struct MPOpts *opts, const char *fname)
talloc_free(slist);
return subnames;
}
-
-char **find_vob_subtitles(struct MPOpts *opts, const char *fname)
-{
- char **vobs = talloc_array_ptrtype(NULL, vobs, 1);
- int n = 0;
-
- // Potential vobsub in the media directory
- struct bstr bname = bstr0(mp_basename(fname));
- int pdot = bstrrchr(bname, '.');
- if (pdot >= 0)
- bname.len = pdot;
- vobs[n++] = mp_path_join(vobs, mp_dirname(fname), bname);
-
- // Potential vobsubs in directories specified by sub-paths option
- if (opts->sub_paths) {
- for (int i = 0; opts->sub_paths[i]; i++) {
- char *path = mp_path_join(NULL, mp_dirname(fname),
- bstr0(opts->sub_paths[i]));
- MP_GROW_ARRAY(vobs, n);
- vobs[n++] = mp_path_join(vobs, bstr0(path), bname);
- talloc_free(path);
- }
- }
-
- // Potential vobsub in ~/.mplayer/sub
- char *mp_subdir = get_path("sub/");
- if (mp_subdir) {
- MP_GROW_ARRAY(vobs, n);
- vobs[n++] = mp_path_join(vobs, bstr0(mp_subdir), bname);
- }
-
- free(mp_subdir);
- MP_RESIZE_ARRAY(NULL, vobs, n);
- return vobs;
-}
diff --git a/sub/find_subfiles.h b/sub/find_subfiles.h
index c93164c6f8..6d68d6140c 100644
--- a/sub/find_subfiles.h
+++ b/sub/find_subfiles.h
@@ -24,6 +24,5 @@
struct MPOpts;
char **find_text_subtitles(struct MPOpts *opts, const char *fname);
-char **find_vob_subtitles(struct MPOpts *opts, const char *fname);
#endif /* MPLAYER_FINDFILES_H */
diff --git a/sub/spudec.c b/sub/spudec.c
index 22f121e92c..59c3058251 100644
--- a/sub/spudec.c
+++ b/sub/spudec.c
@@ -43,7 +43,6 @@
#include "core/mp_msg.h"
#include "spudec.h"
-#include "vobsub.h"
#include "sub.h"
#include "core/mp_common.h"
#include "video/csputils.h"
@@ -659,6 +658,33 @@ void spudec_get_indexed(void *this, struct mp_osd_res *dim,
}
}
+static unsigned int vobsub_palette_to_yuv(unsigned int pal)
+{
+ int r, g, b, y, u, v;
+ // Palette in idx file is not rgb value, it was calculated by wrong formula.
+ // Here's reversed formula of the one used to generate palette in idx file.
+ r = pal >> 16 & 0xff;
+ g = pal >> 8 & 0xff;
+ b = pal & 0xff;
+ y = av_clip_uint8( 0.1494 * r + 0.6061 * g + 0.2445 * b);
+ u = av_clip_uint8( 0.6066 * r - 0.4322 * g - 0.1744 * b + 128);
+ v = av_clip_uint8(-0.08435 * r - 0.3422 * g + 0.4266 * b + 128);
+ y = y * 219 / 255 + 16;
+ return y << 16 | u << 8 | v;
+}
+
+static unsigned int vobsub_rgb_to_yuv(unsigned int rgb)
+{
+ int r, g, b, y, u, v;
+ r = rgb >> 16 & 0xff;
+ g = rgb >> 8 & 0xff;
+ b = rgb & 0xff;
+ y = ( 0.299 * r + 0.587 * g + 0.114 * b) * 219 / 255 + 16.5;
+ u = (-0.16874 * r - 0.33126 * g + 0.5 * b) * 224 / 255 + 128.5;
+ v = ( 0.5 * r - 0.41869 * g - 0.08131 * b) * 224 / 255 + 128.5;
+ return y << 16 | u << 8 | v;
+}
+
static void spudec_parse_extradata(spudec_handle_t *this,
uint8_t *extradata, int extradata_len)
{
diff --git a/sub/vobsub.c b/sub/vobsub.c
deleted file mode 100644
index 5ae7e6cf1a..0000000000
--- a/sub/vobsub.c
+++ /dev/null
@@ -1,980 +0,0 @@
-/*
- * Some code freely inspired from VobSub <URL:http://vobsub.edensrising.com>,
- * with kind permission from Gabest <gabest@freemail.hu>
- *
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include "config.h"
-#include "core/mp_common.h"
-#include "vobsub.h"
-#include "spudec.h"
-#include "core/mp_msg.h"
-#include "core/path.h"
-#include "libavutil/common.h"
-#include "libavutil/intreadwrite.h"
-
-extern int vobsub_id;
-// Record the original -vobsubid set by commandline, since vobsub_id will be
-// overridden if slang match any of vobsub streams.
-static int vobsubid = -2;
-
-typedef FILE rar_stream_t;
-#define rar_open fopen
-#define rar_close fclose
-#define rar_eof feof
-#define rar_tell ftell
-#define rar_seek fseek
-#define rar_getc getc
-#define rar_read fread
-
-/**********************************************************************/
-
-static ssize_t vobsub_getline(char **lineptr, size_t *n, rar_stream_t *stream)
-{
- size_t res = 0;
- int c;
- if (*lineptr == NULL) {
- *lineptr = malloc(4096);
- if (*lineptr)
- *n = 4096;
- } else if (*n == 0) {
- char *tmp = realloc(*lineptr, 4096);
- if (tmp) {
- *lineptr = tmp;
- *n = 4096;
- }
- }
- if (*lineptr == NULL || *n == 0)
- return -1;
-
- for (c = rar_getc(stream); c != EOF; c = rar_getc(stream)) {
- if (res + 1 >= *n) {
- char *tmp = realloc(*lineptr, *n * 2);
- if (tmp == NULL)
- return -1;
- *lineptr = tmp;
- *n *= 2;
- }
- (*lineptr)[res++] = c;
- if (c == '\n') {
- (*lineptr)[res] = 0;
- return res;
- }
- }
- if (res == 0)
- return -1;
- (*lineptr)[res] = 0;
- return res;
-}
-
-/**********************************************************************
- * MPEG parsing
- **********************************************************************/
-
-typedef struct {
- rar_stream_t *stream;
- unsigned int pts;
- int aid;
- unsigned char *packet;
- unsigned int packet_reserve;
- unsigned int packet_size;
- int padding_was_here;
- int merge;
-} mpeg_t;
-
-static mpeg_t *mpeg_open(const char *filename)
-{
- mpeg_t *res = malloc(sizeof(mpeg_t));
- int err = res == NULL;
- if (!err) {
- res->pts = 0;
- res->aid = -1;
- res->packet = NULL;
- res->packet_size = 0;
- res->packet_reserve = 0;
- res->padding_was_here = 1;
- res->merge = 0;
- res->stream = rar_open(filename, "rb");
- err = res->stream == NULL;
- if (err)
- perror("fopen Vobsub file failed");
- if (err)
- free(res);
- }
- return err ? NULL : res;
-}
-
-static void mpeg_free(mpeg_t *mpeg)
-{
- free(mpeg->packet);
- if (mpeg->stream)
- rar_close(mpeg->stream);
- free(mpeg);
-}
-
-static int mpeg_eof(mpeg_t *mpeg)
-{
- return rar_eof(mpeg->stream);
-}
-
-static off_t mpeg_tell(mpeg_t *mpeg)
-{
- return rar_tell(mpeg->stream);
-}
-
-static int mpeg_run(mpeg_t *mpeg)
-{
- unsigned int len, idx, version;
- int c;
- /* Goto start of a packet, it starts with 0x000001?? */
- const unsigned char wanted[] = { 0, 0, 1 };
- unsigned char buf[5];
-
- mpeg->aid = -1;
- mpeg->packet_size = 0;
- if (rar_read(buf, 4, 1, mpeg->stream) != 1)
- return -1;
- while (memcmp(buf, wanted, sizeof(wanted)) != 0) {
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- memmove(buf, buf + 1, 3);
- buf[3] = c;
- }
- switch (buf[3]) {
- case 0xb9: /* System End Code */
- break;
- case 0xba: /* Packet start code */
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- if ((c & 0xc0) == 0x40)
- version = 4;
- else if ((c & 0xf0) == 0x20)
- version = 2;
- else {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Unsupported MPEG version: 0x%02x\n", c);
- return -1;
- }
- if (version == 4) {
- if (rar_seek(mpeg->stream, 9, SEEK_CUR))
- return -1;
- } else if (version == 2) {
- if (rar_seek(mpeg->stream, 7, SEEK_CUR))
- return -1;
- } else
- abort();
- if (!mpeg->padding_was_here)
- mpeg->merge = 1;
- break;
- case 0xbd: /* packet */
- if (rar_read(buf, 2, 1, mpeg->stream) != 1)
- return -1;
- mpeg->padding_was_here = 0;
- len = buf[0] << 8 | buf[1];
- idx = mpeg_tell(mpeg);
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- if ((c & 0xC0) == 0x40) { /* skip STD scale & size */
- if (rar_getc(mpeg->stream) < 0)
- return -1;
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- }
- if ((c & 0xf0) == 0x20) { /* System-1 stream timestamp */
- /* Do we need this? */
- abort();
- } else if ((c & 0xf0) == 0x30) {
- /* Do we need this? */
- abort();
- } else if ((c & 0xc0) == 0x80) { /* System-2 (.VOB) stream */
- unsigned int pts_flags, hdrlen, dataidx;
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- pts_flags = c;
- c = rar_getc(mpeg->stream);
- if (c < 0)
- return -1;
- hdrlen = c;
- dataidx = mpeg_tell(mpeg) + hdrlen;
- if (dataidx > idx + len) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "Invalid header length: %d (total length: %d, idx: %d, dataidx: %d)\n",
- hdrlen, len, idx, dataidx);
- return -1;
- }
- if ((pts_flags & 0xc0) == 0x80) {
- if (rar_read(buf, 5, 1, mpeg->stream) != 1)
- return -1;
- if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) && (buf[2] & 1) && (buf[4] & 1))) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "vobsub PTS error: 0x%02x %02x%02x %02x%02x \n",
- buf[0], buf[1], buf[2], buf[3], buf[4]);
- mpeg->pts = 0;
- } else
- mpeg->pts = ((buf[0] & 0x0e) << 29 | buf[1] << 22 | (buf[2] & 0xfe) << 14
- | buf[3] << 7 | (buf[4] >> 1));
- } else /* if ((pts_flags & 0xc0) == 0xc0) */ {
- /* what's this? */
- /* abort(); */
- }
- rar_seek(mpeg->stream, dataidx, SEEK_SET);
- mpeg->aid = rar_getc(mpeg->stream);
- if (mpeg->aid < 0) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "Bogus aid %d\n", mpeg->aid);
- return -1;
- }
- mpeg->packet_size = len - ((unsigned int) mpeg_tell(mpeg) - idx);
- if (mpeg->packet_reserve < mpeg->packet_size) {
- free(mpeg->packet);
- mpeg->packet = malloc(mpeg->packet_size);
- if (mpeg->packet)
- mpeg->packet_reserve = mpeg->packet_size;
- }
- if (mpeg->packet == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_FATAL, "malloc failure");
- mpeg->packet_reserve = 0;
- mpeg->packet_size = 0;
- return -1;
- }
- if (rar_read(mpeg->packet, mpeg->packet_size, 1, mpeg->stream) != 1) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "fread failure");
- mpeg->packet_size = 0;
- return -1;
- }
- idx = len;
- }
- break;
- case 0xbe: /* Padding */
- if (rar_read(buf, 2, 1, mpeg->stream) != 1)
- return -1;
- len = buf[0] << 8 | buf[1];
- if (len > 0 && rar_seek(mpeg->stream, len, SEEK_CUR))
- return -1;
- mpeg->padding_was_here = 1;
- break;
- default:
- if (0xc0 <= buf[3] && buf[3] < 0xf0) {
- /* MPEG audio or video */
- if (rar_read(buf, 2, 1, mpeg->stream) != 1)
- return -1;
- len = buf[0] << 8 | buf[1];
- if (len > 0 && rar_seek(mpeg->stream, len, SEEK_CUR))
- return -1;
- } else {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "unknown header 0x%02X%02X%02X%02X\n",
- buf[0], buf[1], buf[2], buf[3]);
- return -1;
- }
- }
- return 0;
-}
-
-/**********************************************************************
- * Packet queue
- **********************************************************************/
-
-typedef struct {
- unsigned int pts100;
- off_t filepos;
- unsigned int size;
- unsigned char *data;
-} packet_t;
-
-typedef struct {
- char *id;
- packet_t *packets;
- unsigned int packets_reserve;
- unsigned int packets_size;
- unsigned int current_index;
-} packet_queue_t;
-
-static void packet_construct(packet_t *pkt)
-{
- pkt->pts100 = 0;
- pkt->filepos = 0;
- pkt->size = 0;
- pkt->data = NULL;
-}
-
-static void packet_destroy(packet_t *pkt)
-{
- free(pkt->data);
-}
-
-static void packet_queue_construct(packet_queue_t *queue)
-{
- queue->id = NULL;
- queue->packets = NULL;
- queue->packets_reserve = 0;
- queue->packets_size = 0;
- queue->current_index = 0;
-}
-
-static void packet_queue_destroy(packet_queue_t *queue)
-{
- if (queue->packets) {
- while (queue->packets_size--)
- packet_destroy(queue->packets + queue->packets_size);
- free(queue->packets);
- }
- return;
-}
-
-/* Make sure there is enough room for needed_size packets in the
- packet queue. */
-static int packet_queue_ensure(packet_queue_t *queue, unsigned int needed_size)
-{
- if (queue->packets_reserve < needed_size) {
- if (queue->packets) {
- packet_t *tmp = realloc(queue->packets, 2 * queue->packets_reserve * sizeof(packet_t));
- if (tmp == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_FATAL, "realloc failure");
- return -1;
- }
- queue->packets = tmp;
- queue->packets_reserve *= 2;
- } else {
- queue->packets = malloc(sizeof(packet_t));
- if (queue->packets == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_FATAL, "malloc failure");
- return -1;
- }
- queue->packets_reserve = 1;
- }
- }
- return 0;
-}
-
-/* add one more packet */
-static int packet_queue_grow(packet_queue_t *queue)
-{
- if (packet_queue_ensure(queue, queue->packets_size + 1) < 0)
- return -1;
- packet_construct(queue->packets + queue->packets_size);
- ++queue->packets_size;
- return 0;
-}
-
-/* insert a new packet, duplicating pts from the current one */
-static int packet_queue_insert(packet_queue_t *queue)
-{
- packet_t *pkts;
- if (packet_queue_ensure(queue, queue->packets_size + 1) < 0)
- return -1;
- /* XXX packet_size does not reflect the real thing here, it will be updated a bit later */
- memmove(queue->packets + queue->current_index + 2,
- queue->packets + queue->current_index + 1,
- sizeof(packet_t) * (queue->packets_size - queue->current_index - 1));
- pkts = queue->packets + queue->current_index;
- ++queue->packets_size;
- ++queue->current_index;
- packet_construct(pkts + 1);
- pkts[1].pts100 = pkts[0].pts100;
- pkts[1].filepos = pkts[0].filepos;
- return 0;
-}
-
-/**********************************************************************
- * Vobsub
- **********************************************************************/
-
-typedef struct {
- unsigned int palette[16];
- int delay;
- unsigned int have_palette;
- unsigned int orig_frame_width, orig_frame_height;
- unsigned int origin_x, origin_y;
- /* index */
- packet_queue_t *spu_streams;
- unsigned int spu_streams_size;
- unsigned int spu_streams_current;
- unsigned int spu_valid_streams_size;
-} vobsub_t;
-
-/* Make sure that the spu stream idx exists. */
-static int vobsub_ensure_spu_stream(vobsub_t *vob, unsigned int index)
-{
- if (index >= vob->spu_streams_size) {
- /* This is a new stream */
- if (vob->spu_streams) {
- packet_queue_t *tmp = realloc(vob->spu_streams, (index + 1) * sizeof(packet_queue_t));
- if (tmp == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "vobsub_ensure_spu_stream: realloc failure");
- return -1;
- }
- vob->spu_streams = tmp;
- } else {
- vob->spu_streams = malloc((index + 1) * sizeof(packet_queue_t));
- if (vob->spu_streams == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "vobsub_ensure_spu_stream: malloc failure");
- return -1;
- }
- }
- while (vob->spu_streams_size <= index) {
- packet_queue_construct(vob->spu_streams + vob->spu_streams_size);
- ++vob->spu_streams_size;
- }
- }
- return 0;
-}
-
-static int vobsub_add_id(vobsub_t *vob, const char *id, size_t idlen,
- const unsigned int index)
-{
- if (vobsub_ensure_spu_stream(vob, index) < 0)
- return -1;
- if (id && idlen) {
- free(vob->spu_streams[index].id);
- vob->spu_streams[index].id = malloc(idlen + 1);
- if (vob->spu_streams[index].id == NULL) {
- mp_msg(MSGT_VOBSUB, MSGL_FATAL, "vobsub_add_id: malloc failure");
- return -1;
- }
- vob->spu_streams[index].id[idlen] = 0;
- memcpy(vob->spu_streams[index].id, id, idlen);
- }
- vob->spu_streams_current = index;
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VOBSUB_ID=%d\n", index);
- if (id && idlen)
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VSID_%d_LANG=%s\n", index, vob->spu_streams[index].id);
- mp_msg(MSGT_VOBSUB, MSGL_V, "[vobsub] subtitle (vobsubid): %d language %s\n",
- index, vob->spu_streams[index].id);
- return 0;
-}
-
-static int vobsub_add_timestamp(vobsub_t *vob, off_t filepos, int ms)
-{
- packet_queue_t *queue;
- packet_t *pkt;
- if (vob->spu_streams == 0) {
- mp_msg(MSGT_VOBSUB, MSGL_WARN, "[vobsub] warning, binning some index entries. Check your index file\n");
- return -1;
- }
- queue = vob->spu_streams + vob->spu_streams_current;
- if (packet_queue_grow(queue) >= 0) {
- pkt = queue->packets + (queue->packets_size - 1);
- pkt->filepos = filepos;
- pkt->pts100 = ms < 0 ? UINT_MAX : (unsigned int)ms * 90;
- return 0;
- }
- return -1;
-}
-
-static int vobsub_parse_id(vobsub_t *vob, const char *line)
-{
- // id: xx, index: n
- size_t idlen;
- const char *p, *q;
- p = line;
- while (isspace(*p))
- ++p;
- q = p;
- while (isalpha(*q))
- ++q;
- idlen = q - p;
- if (idlen == 0)
- return -1;
- ++q;
- while (isspace(*q))
- ++q;
- if (strncmp("index:", q, 6))
- return -1;
- q += 6;
- while (isspace(*q))
- ++q;
- if (!isdigit(*q))
- return -1;
- return vobsub_add_id(vob, p, idlen, atoi(q));
-}
-
-static int vobsub_parse_timestamp(vobsub_t *vob, const char *line)
-{
- int h, m, s, ms;
- int64_t filepos;
- if (sscanf(line, " %02d:%02d:%02d:%03d, filepos: %09"SCNx64,
- &h, &m, &s, &ms, &filepos) != 5)
- return -1;
- return vobsub_add_timestamp(vob, filepos, vob->delay + ms + 1000 * (s + 60 * (m + 60 * h)));
-}
-
-static int vobsub_parse_origin(vobsub_t *vob, const char *line)
-{
- // org: X,Y
- unsigned x, y;
-
- if (sscanf(line, " %u,%u", &x, &y) == 2) {
- vob->origin_x = x;
- vob->origin_y = y;
- return 0;
- }
- return -1;
-}
-
-unsigned int vobsub_palette_to_yuv(unsigned int pal)
-{
- int r, g, b, y, u, v;
- // Palette in idx file is not rgb value, it was calculated by wrong formula.
- // Here's reversed formula of the one used to generate palette in idx file.
- r = pal >> 16 & 0xff;
- g = pal >> 8 & 0xff;
- b = pal & 0xff;
- y = av_clip_uint8( 0.1494 * r + 0.6061 * g + 0.2445 * b);
- u = av_clip_uint8( 0.6066 * r - 0.4322 * g - 0.1744 * b + 128);
- v = av_clip_uint8(-0.08435 * r - 0.3422 * g + 0.4266 * b + 128);
- y = y * 219 / 255 + 16;
- return y << 16 | u << 8 | v;
-}
-
-unsigned int vobsub_rgb_to_yuv(unsigned int rgb)
-{
- int r, g, b, y, u, v;
- r = rgb >> 16 & 0xff;
- g = rgb >> 8 & 0xff;
- b = rgb & 0xff;
- y = ( 0.299 * r + 0.587 * g + 0.114 * b) * 219 / 255 + 16.5;
- u = (-0.16874 * r - 0.33126 * g + 0.5 * b) * 224 / 255 + 128.5;
- v = ( 0.5 * r - 0.41869 * g - 0.08131 * b) * 224 / 255 + 128.5;
- return y << 16 | u << 8 | v;
-}
-
-static int vobsub_parse_delay(vobsub_t *vob, const char *line)
-{
- int h, m, s, ms;
- int forward = 1;
- if (*(line + 7) == '+') {
- forward = 1;
- line++;
- } else if (*(line + 7) == '-') {
- forward = -1;
- line++;
- }
- mp_msg(MSGT_SPUDEC, MSGL_V, "forward=%d", forward);
- h = atoi(line + 7);
- mp_msg(MSGT_VOBSUB, MSGL_V, "h=%d,", h);
- m = atoi(line + 10);
- mp_msg(MSGT_VOBSUB, MSGL_V, "m=%d,", m);
- s = atoi(line + 13);
- mp_msg(MSGT_VOBSUB, MSGL_V, "s=%d,", s);
- ms = atoi(line + 16);
- mp_msg(MSGT_VOBSUB, MSGL_V, "ms=%d", ms);
- vob->delay = (ms + 1000 * (s + 60 * (m + 60 * h))) * forward;
- return 0;
-}
-
-static int vobsub_set_lang(const char *line)
-{
- if (vobsub_id == -1)
- vobsub_id = atoi(line + 8);
- return 0;
-}
-
-static int vobsub_parse_one_line(vobsub_t *vob, rar_stream_t *fd,
- unsigned char **extradata,
- unsigned int *extradata_len)
-{
- ssize_t line_size;
- int res = -1;
- size_t line_reserve = 0;
- char *line = NULL;
- do {
- line_size = vobsub_getline(&line, &line_reserve, fd);
- if (line_size < 0 || line_size > 1000000 ||
- *extradata_len+line_size > 10000000) {
- break;
- }
-
- *extradata = realloc(*extradata, *extradata_len+line_size+1);
- memcpy(*extradata+*extradata_len, line, line_size);
- *extradata_len += line_size;
- (*extradata)[*extradata_len] = 0;
-
- if (*line == 0 || *line == '\r' || *line == '\n' || *line == '#')
- continue;
- else if (strncmp("langidx:", line, 8) == 0)
- res = vobsub_set_lang(line);
- else if (strncmp("delay:", line, 6) == 0)
- res = vobsub_parse_delay(vob, line);
- else if (strncmp("id:", line, 3) == 0)
- res = vobsub_parse_id(vob, line + 3);
- else if (strncmp("org:", line, 4) == 0)
- res = vobsub_parse_origin(vob, line + 4);
- else if (strncmp("timestamp:", line, 10) == 0)
- res = vobsub_parse_timestamp(vob, line + 10);
- else {
- mp_msg(MSGT_VOBSUB, MSGL_V, "vobsub: ignoring %s", line);
- continue;
- }
- if (res < 0)
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "ERROR in %s", line);
- break;
- } while (1);
- free(line);
- return res;
-}
-
-int vobsub_parse_ifo(void* this, const char *const name, unsigned int *palette,
- unsigned int *width, unsigned int *height, int force,
- int sid, char *langid)
-{
- vobsub_t *vob = this;
- int res = -1;
- rar_stream_t *fd = rar_open(name, "rb");
- if (fd == NULL) {
- if (force)
- mp_msg(MSGT_VOBSUB, MSGL_WARN, "VobSub: Can't open IFO file\n");
- } else {
- // parse IFO header
- unsigned char block[0x800];
- const char *const ifo_magic = "DVDVIDEO-VTS";
- if (rar_read(block, sizeof(block), 1, fd) != 1) {
- if (force)
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Can't read IFO header\n");
- } else if (memcmp(block, ifo_magic, strlen(ifo_magic) + 1))
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Bad magic in IFO header\n");
- else {
- unsigned pgci_sector = AV_RB32(block + 0xcc);
- int standard = (block[0x200] & 0x30) >> 4;
- int resolution = (block[0x201] & 0x0c) >> 2;
- *height = standard ? 576 : 480;
- *width = 0;
- switch (resolution) {
- case 0x0:
- *width = 720;
- break;
- case 0x1:
- *width = 704;
- break;
- case 0x2:
- *width = 352;
- break;
- case 0x3:
- *width = 352;
- *height /= 2;
- break;
- default:
- mp_msg(MSGT_VOBSUB, MSGL_WARN, "Vobsub: Unknown resolution %d \n", resolution);
- }
- if (langid && 0 <= sid && sid < 32) {
- unsigned char *tmp = block + 0x256 + sid * 6 + 2;
- langid[0] = tmp[0];
- langid[1] = tmp[1];
- langid[2] = 0;
- }
- if (rar_seek(fd, pgci_sector * sizeof(block), SEEK_SET)
- || rar_read(block, sizeof(block), 1, fd) != 1)
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Can't read IFO PGCI\n");
- else {
- unsigned idx;
- unsigned pgc_offset = AV_RB32(block + 0xc);
- pgc_offset = FFMIN(pgc_offset, sizeof(block) - 0xa4 - 4*16);
- for (idx = 0; idx < 16; ++idx) {
- unsigned char *p = block + pgc_offset + 0xa4 + 4 * idx;
- palette[idx] = AV_RB32(p);
- }
- if (vob)
- vob->have_palette = 1;
- res = 0;
- }
- }
- rar_close(fd);
- }
- return res;
-}
-
-void *vobsub_open(const char *const name, const char *const ifo,
- const int force, void** spu)
-{
- unsigned char *extradata = NULL;
- unsigned int extradata_len = 0;
- vobsub_t *vob = calloc(1, sizeof(vobsub_t));
- if (spu)
- *spu = NULL;
- if (vobsubid == -2)
- vobsubid = vobsub_id;
- if (vob) {
- char *buf;
- buf = malloc(strlen(name) + 5);
- if (buf) {
- rar_stream_t *fd;
- mpeg_t *mpg;
- /* read in the info file */
- if (!ifo) {
- strcpy(buf, name);
- strcat(buf, ".ifo");
- vobsub_parse_ifo(vob, buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force, -1, NULL);
- } else
- vobsub_parse_ifo(vob, ifo, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force, -1, NULL);
- /* read in the index */
- strcpy(buf, name);
- strcat(buf, ".idx");
- fd = rar_open(buf, "rb");
- if (fd == NULL) {
- if (force)
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Can't open IDX file\n");
- else {
- free(buf);
- free(vob);
- return NULL;
- }
- } else {
- while (vobsub_parse_one_line(vob, fd, &extradata, &extradata_len) >= 0)
- /* NOOP */ ;
- rar_close(fd);
- }
- if (spu)
- *spu = spudec_new_scaled(vob->palette, vob->orig_frame_width, vob->orig_frame_height, extradata, extradata_len);
- free(extradata);
-
- /* read the indexed mpeg_stream */
- strcpy(buf, name);
- strcat(buf, ".sub");
- mpg = mpeg_open(buf);
- if (mpg == NULL) {
- if (force)
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: Can't open SUB file\n");
- else {
- free(buf);
- free(vob);
- return NULL;
- }
- } else {
- long last_pts_diff = 0;
- while (!mpeg_eof(mpg)) {
- off_t pos = mpeg_tell(mpg);
- if (mpeg_run(mpg) < 0) {
- if (!mpeg_eof(mpg))
- mp_msg(MSGT_VOBSUB, MSGL_ERR, "VobSub: mpeg_run error\n");
- break;
- }
- if (mpg->packet_size) {
- if ((mpg->aid & 0xe0) == 0x20) {
- unsigned int sid = mpg->aid & 0x1f;
- if (vobsub_ensure_spu_stream(vob, sid) >= 0) {
- packet_queue_t *queue = vob->spu_streams + sid;
- /* get the packet to fill */
- if (queue->packets_size == 0 && packet_queue_grow(queue) < 0)
- abort();
- while (queue->current_index + 1 < queue->packets_size
- && queue->packets[queue->current_index + 1].filepos <= pos)
- ++queue->current_index;
- if (queue->current_index < queue->packets_size) {
- packet_t *pkt;
- if (queue->packets[queue->current_index].data) {
- /* insert a new packet and fix the PTS ! */
- packet_queue_insert(queue);
- queue->packets[queue->current_index].pts100 =
- mpg->pts + last_pts_diff;
- }
- pkt = queue->packets + queue->current_index;
- if (pkt->pts100 != UINT_MAX) {
- if (queue->packets_size > 1)
- last_pts_diff = pkt->pts100 - mpg->pts;
-