demux_ts: change overlapping memcpy to memmove
[mplayer/glamo.git] / TOOLS / subrip.c
blob85ee1c78e0a6c2a01bff11d21acaf75191c17d43
1 /*
2 * Use with CVS JOCR/GOCR.
4 * You will have to change 'vobsub_id' value if you want another subtitle than number 0.
6 * HINT: you can view the subtitle that is being decoded with "display subtitle-*.pgm"
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 /* Make sure this accesses the CVS version of JOCR/GOCR */
24 #define GOCR_PROGRAM "gocr"
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/wait.h>
33 #include "libvo/video_out.h"
34 #include "vobsub.h"
35 #include "spudec.h"
37 /* linking hacks */
38 char *mplayer_version;
40 /* XXX Kludge ahead, this MUST be the same as the definitions found in ../spudec.c */
41 typedef struct packet_t packet_t;
42 struct packet_t {
43 unsigned char *packet;
44 unsigned int palette[4];
45 unsigned int alpha[4];
46 unsigned int control_start; /* index of start of control data */
47 unsigned int current_nibble[2]; /* next data nibble (4 bits) to be
48 processed (for RLE decoding) for
49 even and odd lines */
50 int deinterlace_oddness; /* 0 or 1, index into current_nibble */
51 unsigned int start_col, end_col;
52 unsigned int start_row, end_row;
53 unsigned int width, height, stride;
54 unsigned int start_pts, end_pts;
55 packet_t *next;
57 typedef struct {
58 packet_t *queue_head;
59 packet_t *queue_tail;
60 unsigned int global_palette[16];
61 unsigned int orig_frame_width, orig_frame_height;
62 unsigned char* packet;
63 size_t packet_reserve; /* size of the memory pointed to by packet */
64 unsigned int packet_offset; /* end of the currently assembled fragment */
65 unsigned int packet_size; /* size of the packet once all fragments are assembled */
66 unsigned int packet_pts; /* PTS for this packet */
67 unsigned int palette[4];
68 unsigned int alpha[4];
69 unsigned int cuspal[4];
70 unsigned int custom;
71 unsigned int now_pts;
72 unsigned int start_pts, end_pts;
73 unsigned int start_col, end_col;
74 unsigned int start_row, end_row;
75 unsigned int width, height, stride;
76 size_t image_size; /* Size of the image buffer */
77 unsigned char *image; /* Grayscale value */
78 unsigned char *aimage; /* Alpha value */
79 unsigned int scaled_frame_width, scaled_frame_height;
80 unsigned int scaled_start_col, scaled_start_row;
81 unsigned int scaled_width, scaled_height, scaled_stride;
82 size_t scaled_image_size;
83 unsigned char *scaled_image;
84 unsigned char *scaled_aimage;
85 int auto_palette; /* 1 if we lack a palette and must use an heuristic. */
86 int font_start_level; /* Darkest value used for the computed font */
87 const vo_functions_t *hw_spu;
88 int spu_changed;
89 } spudec_handle_t;
91 int vobsub_id=0;
92 int sub_pos=0;
94 static spudec_handle_t *spudec;
95 static FILE *fsub = NULL;
96 static unsigned int sub_idx = 0;
98 static void
99 process_gocr_output(const char *const fname, unsigned int start, unsigned int end)
101 FILE *file;
102 int temp, h, m, s, ms;
103 int c, bol;
104 file = fopen(fname, "r");
105 if (file == NULL) {
106 perror("fopen failed");
107 return;
109 temp = start;
110 temp /= 90;
111 h = temp / 3600000;
112 temp %= 3600000;
113 m = temp / 60000;
114 temp %= 60000;
115 s = temp / 1000;
116 temp %= 1000;
117 ms = temp;
118 fprintf(fsub, "%d\n%02d:%02d:%02d,%03d --> ", ++sub_idx, h, m, s, ms);
119 temp = end;
120 temp /= 90;
121 h = temp / 3600000;
122 temp %= 3600000;
123 m = temp / 60000;
124 temp %= 60000;
125 s = temp / 1000;
126 temp %= 1000;
127 ms = temp;
128 fprintf(fsub, "%02d:%02d:%02d,%03d\n", h, m, s, ms);
129 bol = 1;
130 while ((c = getc(file)) != EOF) {
131 if (bol) {
132 if (!isspace(c)) {
133 putc(c, fsub);
134 bol=0;
137 else if (!bol) {
138 putc(c, fsub);
139 bol = c == '\n';
142 putc('\n', fsub);
143 fflush(fsub);
144 fclose(file);
147 static void
148 output_pgm(FILE *f, int w, int h, unsigned char *src, unsigned char *srca, int stride)
150 int x, y;
151 fprintf(f,
152 "P5\n"
153 "%d %d\n"
154 "255\n",
155 w, h);
156 for (y = 0; y < h; ++y) {
157 for (x = 0; x < w; ++x) {
158 int res;
159 if (srca[x])
160 res = src[x] * (256 - srca[x]);
161 else
162 res = 0;
163 res = (65535 - res) >> 8;
164 putc(res&0xff, f);
167 src += stride;
168 srca += stride;
170 putc('\n', f);
173 static void
174 draw_alpha(int x0, int y0, int w, int h, unsigned char *src, unsigned char *srca, int stride)
176 FILE *f;
177 char buf[128];
178 char cmd[512];
179 int cmdres;
180 const char *const tmpfname = tmpnam(NULL);
181 sprintf(buf, "subtitle-%d-%d.pgm", spudec->start_pts / 90, spudec->end_pts / 90);
182 f = fopen(buf, "w");
183 output_pgm(f, w, h, src, srca, stride);
184 fclose(f);
185 /* see <URL:http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/subtitleripper/subtitleripper/src/README.gocr?rev=HEAD&content-type=text/vnd.viewcvs-markup> */
186 sprintf(cmd, GOCR_PROGRAM" -v 1 -s 7 -d 0 -m 130 -m 256 -m 32 -i %s -o %s", buf, tmpfname);
187 cmdres = system(cmd);
188 if (cmdres < 0) {
189 perror("system failed");
190 exit(EXIT_FAILURE);
192 else if (cmdres) {
193 fprintf(stderr, GOCR_PROGRAM" returned %d\n", cmdres);
194 exit(cmdres);
196 process_gocr_output(tmpfname, spudec->start_pts, spudec->end_pts);
197 unlink(buf);
198 unlink(tmpfname);
202 main(int argc, char **argv)
204 const char *vobsubname, *subripname;
205 void *vobsub;
206 void *packet;
207 int packet_len;
208 unsigned int pts100;
210 if (argc < 2 || 4 < argc) {
211 fprintf(stderr, "Usage: %s <vobsub basename> [<subid> [<output filename>] ]\n", argv[0]);
212 exit(EXIT_FAILURE);
214 vobsubname = argv[1];
215 subripname = NULL;
216 fsub = stdout;
217 if (argc >= 3)
218 vobsub_id = atoi(argv[2]);
219 if (argc >= 4) {
220 subripname = argv[3];
221 fsub = fopen(subripname, "w");
224 vobsub = vobsub_open(vobsubname, NULL, 0, &spudec);
225 while ((packet_len=vobsub_get_next_packet(vobsub, &packet, &pts100)) >= 0) {
226 spudec_assemble(spudec, packet, packet_len, pts100);
227 if (spudec->queue_head) {
228 spudec_heartbeat(spudec, spudec->queue_head->start_pts);
229 if (spudec_changed(spudec))
230 spudec_draw(spudec, draw_alpha);
234 if (vobsub)
235 vobsub_close(vobsub);
236 exit(EXIT_SUCCESS);