From 4d38521e2cd1e62ef334a73624cbd4a95f1de436 Mon Sep 17 00:00:00 2001 From: kmkaplan Date: Fri, 29 Mar 2002 03:17:57 +0000 Subject: * New command line switch for mplayer & mencoder: -ifo Indicate the file that will be used to load palette and frame size for MPEG subtitles. * mencoder.c: Fix cropping when decoding MPEG2. * spudec.c: If scaling is needed only do it once. Change WITH_NO_ANTIALIASING to ANTIALIASING_ALGORITHM. * vobsub.c: Support reading info regarding size and palette from IDX file instead of IFO file. Support streams containing audio or video. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@5389 b3059339-0415-0410-9bf9-f77b7e298cf2 --- Makefile | 4 +- cfg-common.h | 1 + mencoder.c | 14 ++++- mplayer.c | 10 ++++ spudec.c | 13 +++-- vobsub.c | 180 +++++++++++++++++++++++++++++++++++++++++------------------ vobsub.h | 1 + 7 files changed, 160 insertions(+), 63 deletions(-) diff --git a/Makefile b/Makefile index 05ccb7179a..dbd382f12b 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,9 @@ MANDIR = ${prefix}/man # a BSD compatible 'install' program INSTALL = install -SRCS_COMMON = cyuv.c adpcm.c xacodec.c cpudetect.c mp_msg.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c spudec.c playtree.c playtreeparser.c asxparser.c qtsmc.c ducktm1.c roqav.c qtrpza.c +SRCS_COMMON = cyuv.c adpcm.c xacodec.c cpudetect.c mp_msg.c msvidc.c cinepak.c fli.c qtrle.c codec-cfg.c cfgparser.c my_profile.c RTjpegN.c minilzo.c nuppelvideo.c spudec.c playtree.c playtreeparser.c asxparser.c qtsmc.c ducktm1.c roqav.c qtrpza.c vobsub.c SRCS_MENCODER = mencoder.c $(SRCS_COMMON) libao2/afmt.c divx4_vbr.c libvo/aclib.c libvo/img_format.c libvo/osd.c me-opt-reg.c -SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c lirc_mp.c mixer.c vobsub.c mp-opt-reg.c +SRCS_MPLAYER = mplayer.c $(SRCS_COMMON) find_sub.c subreader.c lirc_mp.c mixer.c mp-opt-reg.c OBJS_MENCODER = $(SRCS_MENCODER:.c=.o) OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) diff --git a/cfg-common.h b/cfg-common.h index f0d6335ad7..5ef0675e74 100644 --- a/cfg-common.h +++ b/cfg-common.h @@ -50,6 +50,7 @@ {"aid", &audio_id, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL}, {"vid", &video_id, CONF_TYPE_INT, CONF_RANGE, 0, 255, NULL}, {"sid", &dvdsub_id, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL}, + {"ifo", &spudec_ifo, CONF_TYPE_STRING, 0, 0, 0, NULL}, // ------------------------- a-v sync options -------------------- diff --git a/mencoder.c b/mencoder.c index ace0745eb0..58fc216efe 100644 --- a/mencoder.c +++ b/mencoder.c @@ -123,6 +123,8 @@ int vcd_track=0; int audio_id=-1; int video_id=-1; int dvdsub_id=-1; +int vobsub_id=-1; +static char* spudec_ifo=NULL; static int has_audio=1; char *audio_codec=NULL; // override audio codec @@ -239,6 +241,7 @@ static int bits_per_pixel(uint32_t fmt); #ifdef USE_DVDREAD #include "spudec.h" #endif +#include "vobsub.h" /* FIXME */ void mencoder_exit(int level, char *how) @@ -270,8 +273,10 @@ void parse_cfgfiles( m_config_t* conf ) static unsigned char* vo_image=NULL; static unsigned char* vo_image_ptr=NULL; -static uint32_t draw_slice(uint8_t *src[], int stride[], int w,int h, int x0,int y0){ +static uint32_t draw_slice(const uint8_t *src0[], int stride[], int w,int h, int x0,int y0){ int y; + uint8_t *src[3]; + memcpy(src, src0, sizeof(src)); // printf("draw_slice %dx%d %d;%d\n",w,h,x0,y0); if(y0 + h < crop_y0) @@ -769,9 +774,16 @@ if(sh_audio && (out_audio_codec || seek_to_sec || !sh_audio->wf)){ // set up video encoder: +if (spudec_ifo) { + unsigned int palette[16], width, height; + if (vobsub_parse_ifo(spudec_ifo, palette, &width, &height, 1) >= 0) + vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); +} +if (vo_spudec==NULL) { #ifdef USE_DVDREAD vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL, sh_video->disp_w, sh_video->disp_h); +} #endif // set up output file: diff --git a/mplayer.c b/mplayer.c index 1ad9608c6a..b0d8771dc2 100644 --- a/mplayer.c +++ b/mplayer.c @@ -205,6 +205,7 @@ int dvdsub_id=-1; int vobsub_id=-1; char* audio_lang=NULL; char* dvdsub_lang=NULL; +static char* spudec_ifo=NULL; static int vcd_track=0; // cache2: @@ -1107,10 +1108,19 @@ demux_info_print(demuxer); //================== Read SUBTITLES (DVD & TEXT) ========================== if(sh_video){ +current_module="spudec"; +if (spudec_ifo) { + unsigned int palette[16], width, height; + if (vobsub_parse_ifo(spudec_ifo, palette, &width, &height, 1) >= 0) + vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); +} + #ifdef USE_DVDREAD +if (vo_spudec==NULL) { current_module="spudec_init"; vo_spudec=spudec_new_scaled(stream->type==STREAMTYPE_DVD?((dvd_priv_t *)(stream->priv))->cur_pgc->palette:NULL, sh_video->disp_w, sh_video->disp_h); +} if (vo_spudec!=NULL) inited_flags|=INITED_SPUDEC; #endif diff --git a/spudec.c b/spudec.c index b1f143f23e..de2f57e800 100644 --- a/spudec.c +++ b/spudec.c @@ -26,7 +26,7 @@ #include #include #include -#ifndef WITH_NO_ANTIALIASING +#if ANTIALIASING_ALGORITHM == 2 #include #endif #include "spudec.h" @@ -55,7 +55,7 @@ typedef struct { size_t image_size; /* Size of the image buffer */ unsigned char *image; /* Grayscale value */ unsigned char *aimage; /* Alpha value */ - int scaled; /* flag if the image has already been scaled */ + unsigned int scaled_frame_width, scaled_frame_height; unsigned int scaled_start_col, scaled_start_row; unsigned int scaled_width, scaled_height, scaled_stride; size_t scaled_image_size; @@ -116,7 +116,8 @@ static void spudec_process_data(spudec_handle_t *this) unsigned int cmap[4], alpha[4]; unsigned int i, x, y; - this->scaled = 0; + this->scaled_frame_width = 0; + this->scaled_frame_height = 0; for (i = 0; i < 4; ++i) { alpha[i] = mkalpha(this->alpha[i]); if (alpha[i] == 0) @@ -389,8 +390,7 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra spu->image, spu->aimage, spu->stride); } else { - if (!spu->scaled || - spu->orig_frame_width != dxs || spu->orig_frame_height != dys) { /* Resizing is needed */ + if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */ /* scaled_x = scalex * x / 0x100 scaled_y = scaley * y / 0x100 order of operations is important because of rounding. */ @@ -642,7 +642,8 @@ void spudec_draw_scaled(void *me, unsigned int dxs, unsigned int dys, void (*dra } } #endif - spu->scaled = 1; + spu->scaled_frame_width = dxs; + spu->scaled_frame_height = dys; } } if (spu->scaled_image) diff --git a/vobsub.c b/vobsub.c index 8919ca94d2..ee61d8a7b5 100644 --- a/vobsub.c +++ b/vobsub.c @@ -270,7 +270,20 @@ mpeg_run(mpeg_t *mpeg) return -1; break; default: - return -1; + if (0xc0 <= buf[3] && buf[3] < 0xf0) { + /* MPEG audio or video */ + if (stream_read(mpeg->stream, buf, 2) != 2) + return -1; + len = buf[0] << 8 | buf[1]; + if (len > 0 && !stream_skip(mpeg->stream, len)) + return -1; + + } + else { + fprintf(stderr, "unknown header 0x%02X%02X%02X%02X\n", + buf[0], buf[1], buf[2], buf[3]); + return -1; + } } return 0; } @@ -396,6 +409,7 @@ packet_queue_insert(packet_queue_t *queue) typedef struct { void *spudec; unsigned int palette[16]; + unsigned int orig_frame_width, orig_frame_height; /* index */ packet_queue_t *spu_streams; unsigned int spu_streams_size; @@ -556,6 +570,48 @@ vobsub_parse_timestamp(vobsub_t *vob, const char *line) return vobsub_add_timestamp(vob, filepos, ms + 1000 * (s + 60 * (m + 60 * h))); } +static int +vobsub_parse_size(vobsub_t *vob, const char *line) +{ + // size: WWWxHHH + char *p; + while (isspace(*line)) + ++line; + if (!isdigit(*line)) + return -1; + vob->orig_frame_width = strtoul(line, &p, 10); + if (*p != 'x') + return -1; + ++p; + vob->orig_frame_height = strtoul(p, NULL, 10); + return 0; +} + +static int +vobsub_parse_palette(vobsub_t *vob, const char *line) +{ + // palette: XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX, XXXXXX + unsigned int n; + n = 0; + while (1) { + const char *p; + while (isspace(*line)) + ++line; + p = line; + while (isxdigit(*p)) + ++p; + if (p - line != 6) + return -1; + vob->palette[n++] = strtoul(line, NULL, 16); + if (n == 16) + break; + if (*p == ',') + ++p; + line = p; + } + return 0; +} + static int vobsub_parse_one_line(vobsub_t *vob, FILE *fd) { @@ -574,6 +630,10 @@ vobsub_parse_one_line(vobsub_t *vob, FILE *fd) continue; else if (strncmp("id:", line, 3) == 0) res = vobsub_parse_id(vob, line + 3); + else if (strncmp("palette:", line, 8) == 0) + res = vobsub_parse_palette(vob, line + 8); + else if (strncmp("size:", line, 5) == 0) + res = vobsub_parse_size(vob, line + 5); else if (strncmp("timestamp:", line, 10) == 0) res = vobsub_parse_timestamp(vob, line + 10); else { @@ -588,6 +648,65 @@ vobsub_parse_one_line(vobsub_t *vob, FILE *fd) return res; } +int +vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force) +{ + int res = -1; + FILE *fd = fopen(name, "rb"); + if (fd == NULL) + perror("Can't open IFO file"); + else { + // parse IFO header + unsigned char block[0x800]; + const char *const ifo_magic = "DVDVIDEO-VTS"; + if (fread(block, sizeof(block), 1, fd) != 1) { + if (force) + perror("Can't read IFO header"); + } else if (memcmp(block, ifo_magic, strlen(ifo_magic) + 1)) + fprintf(stderr, "Bad magic in IFO header\n"); + else { + unsigned long pgci_sector = block[0xcc] << 24 | block[0xcd] << 16 + | block[0xce] << 8 | block[0xcf]; + 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: + fprintf(stderr, "Unknown resolution %d \n", resolution); + } + if (fseek(fd, pgci_sector * sizeof(block), SEEK_SET) + || fread(block, sizeof(block), 1, fd) != 1) + perror("Can't read IFO PGCI"); + else { + unsigned long idx; + unsigned long pgc_offset = block[0xc] << 24 | block[0xd] << 16 + | block[0xe] << 8 | block[0xf]; + for (idx = 0; idx < 16; ++idx) { + unsigned char *p = block + pgc_offset + 0xa4 + 4 * idx; + palette[idx] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; + } + res = 0; + } + } + fclose(fd); + } + return res; +} + void * vobsub_open(const char *const name, const int force) { @@ -595,6 +714,8 @@ vobsub_open(const char *const name, const int force) if (vob) { char *buf; vob->spudec = NULL; + vob->orig_frame_width = 0; + vob->orig_frame_height = 0; vob->spu_streams = NULL; vob->spu_streams_size = 0; vob->spu_streams_current = 0; @@ -602,61 +723,10 @@ vobsub_open(const char *const name, const int force) if (buf) { FILE *fd; mpeg_t *mpg; + /* read in the info file */ strcpy(buf, name); strcat(buf, ".ifo"); - fd = fopen(buf, "rb"); - if (fd == NULL) { - if(force) - perror("VobSub: Can't open IFO file"); - } else { - // parse IFO header - unsigned char block[0x800]; - const char *const ifo_magic = "DVDVIDEO-VTS"; - if (fread(block, sizeof(block), 1, fd) != 1) - perror("Can't read IFO header"); - else if (memcmp(block, ifo_magic, strlen(ifo_magic) + 1)) - fprintf(stderr, "Bad magic in IFO header\n"); - else { - unsigned long pgci_sector = block[0xcc] << 24 | block[0xcd] << 16 - | block[0xce] << 8 | block[0xcf]; - int standard = (block[0x200] & 0x30) >> 4; - int resolution = (block[0x201] & 0x0c) >> 2; - unsigned int orig_frame_y = standard ? 576 : 480; - unsigned int orig_frame_x = 0; - switch (resolution) { - case 0x0: - orig_frame_x = 720; - break; - case 0x1: - orig_frame_x = 704; - break; - case 0x2: - orig_frame_x = 352; - break; - case 0x3: - orig_frame_x = 352; - orig_frame_y /= 2; - break; - default: - fprintf(stderr, "Unknown resolution %d \n", resolution); - } - if (fseek(fd, pgci_sector * sizeof(block), SEEK_SET) - || fread(block, sizeof(block), 1, fd) != 1) - perror("Can't read IFO PGCI"); - else { - unsigned long idx; - unsigned long pgc_offset = block[0xc] << 24 | block[0xd] << 16 - | block[0xe] << 8 | block[0xf]; - for (idx = 0; idx < 16; ++idx) { - unsigned char *p = block + pgc_offset + 0xa4 + 4 * idx; - vob->palette[idx] = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3]; - } - } - vob->spudec = spudec_new_scaled(vob->palette, orig_frame_x, orig_frame_y); - } - fclose(fd); - } - + vobsub_parse_ifo(buf, vob->palette, &vob->orig_frame_width, &vob->orig_frame_height, force); /* read in the index */ strcpy(buf, name); strcat(buf, ".idx"); @@ -671,6 +741,8 @@ vobsub_open(const char *const name, const int force) /* NOOP */ ; fclose(fd); } + if (vob->orig_frame_width && vob->orig_frame_height) + vob->spudec = spudec_new_scaled(vob->palette, vob->orig_frame_width, vob->orig_frame_height); /* read the indexed mpeg_stream */ strcpy(buf, name); diff --git a/vobsub.h b/vobsub.h index b26aa8aa5d..a5700c06b3 100644 --- a/vobsub.h +++ b/vobsub.h @@ -5,5 +5,6 @@ extern void *vobsub_open(const char *subname, const int force); extern void vobsub_process(void *vob, float pts); extern void vobsub_reset(void *vob); extern void vobsub_draw(void *vob, int dxs, int dys, void (*draw_alpha)(int x0,int y0, int w,int h, unsigned char* src, unsigned char *srca, int stride)); +extern int vobsub_parse_ifo(const char *const name, unsigned int *palette, unsigned int *width, unsigned int *height, int force); #endif /* MPLAYER_VOBSUB_H */ -- cgit v1.2.3