changeset 6830:032137fe69a5

Transform Vobsub subtitles into Subrip text subtitles using GOCR/JOCR.
author kmkaplan
date Sun, 28 Jul 2002 16:30:52 +0000
parents d7db9f1b1d36
children f628e5dca5b9
files TOOLS/subrip.c
diffstat 1 files changed, 211 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TOOLS/subrip.c	Sun Jul 28 16:30:52 2002 +0000
@@ -0,0 +1,211 @@
+/* -*- compile-command: "gcc -g -Wall -I.. -o subrip subrip.c ../vobsub.o ../spudec.o ../mp_msg.o" -*- */
+/*
+ * Use with CVS JOCR/GOCR.
+ *
+ * You will have to change 'vobsub_id' value if you want another subtitle than number 0.
+ *
+ * HINT: you can view the subtitle that is being decoded with "display subtitle-*.pgm"
+ *
+ */
+
+/* Make sure this accesses the CVS version of JOCR/GOCR */
+#define GOCR_PROGRAM "/usr/local/src/cvs/jocr/jocr/src/gocr"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "libvo/video_out.h"
+#include "vobsub.h"
+#include "spudec.h"
+
+/* XXX Kludge ahead, this MUST be the same as the definition found in ../spudec.c */
+typedef struct {
+  unsigned int global_palette[16];
+  unsigned int orig_frame_width, orig_frame_height;
+  unsigned char* packet;
+  size_t packet_reserve;	/* size of the memory pointed to by packet */
+  unsigned int packet_offset;	/* end of the currently assembled fragment */
+  unsigned int packet_size;	/* size of the packet once all fragments are assembled */
+  unsigned int packet_pts;	/* PTS for this packet */
+  unsigned int control_start;	/* index of start of control data */
+  unsigned int palette[4];
+  unsigned int alpha[4];
+  unsigned int cuspal[4];
+  unsigned int custom;
+  unsigned int now_pts;
+  unsigned int start_pts, end_pts;
+  unsigned int start_col, end_col;
+  unsigned int start_row, end_row;
+  unsigned int width, height, stride;
+  unsigned int current_nibble[2]; /* next data nibble (4 bits) to be
+                                     processed (for RLE decoding) for
+                                     even and odd lines */
+  int deinterlace_oddness;	/* 0 or 1, index into current_nibble */
+  size_t image_size;		/* Size of the image buffer */
+  unsigned char *image;		/* Grayscale value */
+  unsigned char *aimage;	/* Alpha value */
+  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;
+  unsigned char *scaled_image;
+  unsigned char *scaled_aimage;
+  int auto_palette; /* 1 if we lack a palette and must use an heuristic. */
+  int font_start_level;  /* Darkest value used for the computed font */
+  vo_functions_t *hw_spu;
+  int spu_changed;
+} spudec_handle_t;
+
+int use_gui;
+int gtkMessageBox;
+int verbose=1;
+int vobsub_id=0;
+
+static spudec_handle_t *spudec;
+static FILE *fsub = NULL;
+static unsigned int sub_idx = 0;
+
+static void
+process_gocr_output(const char *const fname, unsigned int start, unsigned int end)
+{
+    FILE *file;
+    int temp, h, m, s, ms;
+    int c, bol;
+    file = fopen(fname, "r");
+    if (file == NULL) {
+	perror("fopen failed");
+	return;
+    }
+    temp = start;
+    temp /= 90;
+    h = temp / 3600000;
+    temp %= 3600000;
+    m = temp / 60000;
+    temp %= 60000;
+    s = temp / 1000;
+    temp %= 1000;
+    ms = temp;
+    fprintf(fsub, "%d\n%02d:%02d:%02d,%03d --> ", ++sub_idx, h, m, s, ms);
+    temp = end;
+    temp /= 90;
+    h = temp / 3600000;
+    temp %= 3600000;
+    m = temp / 60000;
+    temp %= 60000;
+    s = temp / 1000;
+    temp %= 1000;
+    ms = temp;
+    fprintf(fsub, "%02d:%02d:%02d,%03d\n", h, m, s, ms);
+    bol = 1;
+    while ((c = getc(file)) != EOF) {
+	if (bol) {
+	    if (!isspace(c)) {
+		putc(c, fsub);
+		bol=0;
+	    }
+	}
+	else if (!bol) {
+	    putc(c, fsub);
+	    bol = c == '\n';
+	}
+    }
+    putc('\n', fsub);
+    fflush(fsub);
+    fclose(file);
+}
+
+static void
+output_pgm(FILE *f, int w, int h, unsigned char *src, unsigned char *srca, int stride)
+{
+    int x, y;
+    fprintf(f,
+	    "P5\n"
+	    "%d %d\n"
+	    "255\n",
+	    w, h);
+    for (y = 0; y < h; ++y) {
+	for (x = 0; x < w; ++x) {
+	    int res;
+	    if (srca[x])
+		res = src[x] * (256 - srca[x]);
+	    else
+		res = 0;
+	    res = (65535 - res) >> 8;
+	    putc(res&0xff, f);
+
+	}
+	src += stride;
+	srca += stride;
+    }
+    putc('\n', f);
+}
+
+static void
+draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
+{
+    FILE *f;
+    char buf[128];
+    char cmd[512];
+    int cmdres;
+    const char *const tmpfname = tmpnam(NULL);
+    sprintf(buf, "subtitle-%d-%d.pgm", spudec->start_pts / 90, spudec->end_pts / 90);
+    f = fopen(buf, "w");
+    output_pgm(f, w, h, src, srca, stride);
+    fclose(f);
+    /* see <URL:http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/subtitleripper/subtitleripper/src/README.gocr?rev=HEAD&content-type=text/vnd.viewcvs-markup> */
+    sprintf(cmd, GOCR_PROGRAM" -v 1 -s 7 -d 0 -m 130 -m 256 -m 32 -i %s -o %s", buf, tmpfname);
+    cmdres = system(cmd);
+    if (cmdres < 0) {
+	perror("system failed");
+	exit(EXIT_FAILURE);
+    }
+    else if (cmdres) {
+	fprintf(stderr, GOCR_PROGRAM" returned %d\n", cmdres);
+	exit(cmdres);
+    }
+    process_gocr_output(tmpfname, spudec->start_pts, spudec->end_pts);
+    unlink(buf);
+    unlink(tmpfname);
+}
+
+int
+main(int argc, char **argv)
+{
+    const char *vobsubname, *subripname;
+    void *vobsub;
+    void *packet;
+    int packet_len;
+#ifdef BAD
+    unsigned int prev_pts;
+#endif
+    unsigned int pts100;
+
+    if (argc < 2 || 4 < argc) {
+	fprintf(stderr, "Usage: %s <vobsub basename> [<subid> [<output filename>] ]\n", argv[0]);
+	exit(EXIT_FAILURE);
+    }
+    vobsubname = argv[1];
+    subripname = NULL;
+    fsub = stdout;
+    if (argc >= 3)
+	vobsub_id = atoi(argv[2]);
+    if (argc >= 4) {
+	subripname = argv[3];
+	fsub = fopen(subripname, "w");
+    }
+
+    vobsub = vobsub_open(vobsubname, NULL, 0, &spudec);
+    while ((packet_len=vobsub_get_next_packet(vobsub, &packet, &pts100)) >= 0) {
+	spudec_assemble(spudec, packet, packet_len, pts100);
+	spudec_heartbeat(spudec, spudec->start_pts);
+	if (spudec_changed(spudec)) 
+	    spudec_draw(spudec, draw_alpha);
+    }
+
+    if (vobsub)
+	vobsub_close(vobsub);
+    exit(EXIT_SUCCESS);
+}