changeset 5388:3af2729c5c87

* New command line switch for mplayer & mencoder: -ifo <ifo file> 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.
author kmkaplan
date Fri, 29 Mar 2002 03:17:57 +0000
parents 44661cb881d0
children 7296c4262457
files Makefile cfg-common.h mencoder.c mplayer.c spudec.c vobsub.c vobsub.h
diffstat 7 files changed, 160 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Fri Mar 29 02:52:45 2002 +0000
+++ b/Makefile	Fri Mar 29 03:17:57 2002 +0000
@@ -37,9 +37,9 @@
 # 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)
--- a/cfg-common.h	Fri Mar 29 02:52:45 2002 +0000
+++ b/cfg-common.h	Fri Mar 29 03:17:57 2002 +0000
@@ -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 --------------------
 
--- a/mencoder.c	Fri Mar 29 02:52:45 2002 +0000
+++ b/mencoder.c	Fri Mar 29 03:17:57 2002 +0000
@@ -123,6 +123,8 @@
 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 @@
 #ifdef USE_DVDREAD
 #include "spudec.h"
 #endif
+#include "vobsub.h"
 
 /* FIXME */
 void mencoder_exit(int level, char *how)
@@ -270,8 +273,10 @@
 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 @@
 
 // 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:
--- a/mplayer.c	Fri Mar 29 02:52:45 2002 +0000
+++ b/mplayer.c	Fri Mar 29 03:17:57 2002 +0000
@@ -205,6 +205,7 @@
 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 @@
 //================== 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
--- a/spudec.c	Fri Mar 29 02:52:45 2002 +0000
+++ b/spudec.c	Fri Mar 29 03:17:57 2002 +0000
@@ -26,7 +26,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#ifndef WITH_NO_ANTIALIASING
+#if ANTIALIASING_ALGORITHM == 2
 #include <math.h>
 #endif
 #include "spudec.h"
@@ -55,7 +55,7 @@
   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 @@
   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 @@
 		   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 @@
 	    }
 	  }
 #endif
-	  spu->scaled = 1;
+	  spu->scaled_frame_width = dxs;
+	  spu->scaled_frame_height = dys;
 	}
       }
       if (spu->scaled_image)
--- a/vobsub.c	Fri Mar 29 02:52:45 2002 +0000
+++ b/vobsub.c	Fri Mar 29 03:17:57 2002 +0000
@@ -270,7 +270,20 @@
 	    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 @@
 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;
@@ -557,6 +571,48 @@
 }
 
 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)
 {
     ssize_t line_size;
@@ -574,6 +630,10 @@
 	    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 @@
     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 @@
     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 @@
 	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 @@
 		    /* 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);
--- a/vobsub.h	Fri Mar 29 02:52:45 2002 +0000
+++ b/vobsub.h	Fri Mar 29 03:17:57 2002 +0000
@@ -5,5 +5,6 @@
 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 */