15886
|
1 /*
|
|
2 * avisubdump
|
|
3 *
|
|
4 * avi vobsub subtitle stream dumper (c) 2004 Tobias Diedrich
|
|
5 * Licensed under GNU GPLv2 or (at your option) any later version.
|
|
6 *
|
15891
|
7 * The subtitles are dumped to stdout.
|
15886
|
8 */
|
|
9
|
|
10 #include <unistd.h>
|
|
11 #include <stdio.h>
|
|
12 #include <stdlib.h>
|
|
13 #include <string.h>
|
|
14 #include <fcntl.h>
|
|
15 #include <errno.h>
|
|
16
|
|
17 #define FCC(a,b,c,d) (((a))|((b)<<8)|((c)<<16)|((d)<<24))
|
|
18
|
|
19 #define FCC_RIFF FCC('R','I','F','F')
|
|
20 #define FCC_LIST FCC('L','I','S','T')
|
|
21 #define FCC_strh FCC('s','t','r','h')
|
|
22 #define FCC_txts FCC('t','x','t','s')
|
|
23 #define FCC_GAB2 FCC('G','A','B','2')
|
|
24
|
|
25 #define GAB_LANGUAGE 0
|
|
26 #define GAB_ENTRY 1
|
|
27 #define GAB_LANGUAGE_UNICODE 2
|
|
28 #define GAB_ENTRY_UNICODE 3
|
|
29 #define GAB_RAWTEXTSUBTITLE 4
|
|
30
|
|
31 static unsigned int getle16(FILE* f){
|
|
32 unsigned int res;
|
|
33
|
|
34 res = fgetc(f);
|
|
35 res |= fgetc(f) << 8;
|
|
36
|
|
37 return res;
|
|
38 }
|
|
39
|
|
40 static unsigned int getle(FILE* f){
|
|
41 unsigned int res;
|
|
42
|
|
43 res = fgetc(f);
|
|
44 res |= fgetc(f) << 8;
|
|
45 res |= fgetc(f) << 16;
|
|
46 res |= fgetc(f) << 24;
|
|
47
|
|
48 return res;
|
|
49 }
|
|
50
|
|
51 static void skip(FILE *f, int len)
|
|
52 {
|
|
53 if (f != stdin) {
|
|
54 fseek(f,len,SEEK_CUR);
|
|
55 } else {
|
|
56 void *buf = malloc(len);
|
|
57 fread(buf,len,1,f);
|
|
58 free(buf);
|
|
59 }
|
|
60 }
|
|
61
|
|
62 static int stream_id(unsigned int id)
|
|
63 {
|
|
64 char c1,c2;
|
|
65 c1 = (char)(id & 0xff);
|
|
66 c2 = (char)((id >> 8) & 0xff);
|
|
67 if (c1 >= '0' && c1 <= '9' &&
|
|
68 c2 >= '0' && c2 <= '9') {
|
|
69 c1 -= '0';
|
|
70 c2 -= '0';
|
|
71 return c1*10+c2;
|
|
72 }
|
|
73 return -1;
|
|
74 }
|
|
75
|
|
76 static int dumpsub_gab2(FILE *f, int size) {
|
|
77 int ret = 0;
|
|
78
|
|
79 while (ret + 6 <= size) {
|
|
80 unsigned int len, id;
|
|
81 char *buf;
|
15891
|
82 int i;
|
15886
|
83
|
|
84 id = getle16(f); ret += 2;
|
|
85 len = getle(f); ret += 4;
|
|
86 if (ret + len > size) break;
|
|
87
|
|
88 buf = malloc(len);
|
|
89 ret += fread(buf, 1, len, f);
|
|
90
|
|
91 switch (id) {
|
15891
|
92 case GAB_LANGUAGE_UNICODE: /* FIXME: convert to utf-8; endianness */
|
15886
|
93 for (i=0; i<len; i++) buf[i] = buf[i*2];
|
|
94 case GAB_LANGUAGE:
|
|
95 fprintf(stderr, "LANGUAGE: %s\n", buf);
|
|
96 break;
|
15891
|
97 case GAB_ENTRY_UNICODE: /* FIXME: convert to utf-8; endianness */
|
15886
|
98 for (i=0; i<len; i++) buf[i] = buf[i*2];
|
|
99 case GAB_ENTRY:
|
|
100 fprintf(stderr, "ENTRY: %s\n", buf);
|
|
101 break;
|
|
102 case GAB_RAWTEXTSUBTITLE:
|
|
103 printf("%s", buf);
|
|
104 break;
|
|
105 default:
|
|
106 fprintf(stderr, "Unknown type %d, len %d\n", id, len);
|
|
107 break;
|
|
108 }
|
|
109 free(buf);
|
|
110 }
|
|
111
|
|
112 return ret;
|
|
113 }
|
|
114
|
|
115 static void dump(FILE *f) {
|
|
116 unsigned int id, len;
|
|
117 int stream = 0;
|
|
118 int substream = -2;
|
|
119
|
|
120 while (1) {
|
|
121 id = getle(f);
|
|
122 len = getle(f);
|
|
123
|
|
124 if(feof(f)) break;
|
|
125
|
|
126 if (id == FCC_RIFF ||
|
|
127 id == FCC_LIST) {
|
|
128 getle(f);
|
|
129 continue;
|
|
130 } else if (id == FCC_strh) {
|
|
131 id = getle(f); len -= 4;
|
|
132 fprintf(stderr, "Stream %d is %c%c%c%c",
|
|
133 stream,
|
|
134 id,
|
|
135 id >> 8,
|
|
136 id >> 16,
|
|
137 id >> 24);
|
|
138 if (id == FCC_txts) {
|
|
139 substream = stream;
|
|
140 fprintf(stderr, " (subtitle stream)");
|
|
141 }
|
|
142 fprintf(stderr, ".\n");
|
|
143 stream++;
|
|
144 } else if (stream_id(id) == substream) {
|
|
145 unsigned int subid;
|
|
146 subid = getle(f); len -= 4;
|
|
147 if (subid != FCC_GAB2) {
|
|
148 fprintf(stderr,
|
|
149 "Unknown subtitle chunk %c%c%c%c (%08x).\n",
|
|
150 id, id >> 8, id >> 16, id >> 24, subid);
|
|
151 } else {
|
|
152 skip(f,1); len -= 1;
|
|
153 len -= dumpsub_gab2(f, len);
|
|
154 }
|
|
155 }
|
|
156 len+=len&1;
|
|
157 skip(f,len);
|
|
158 }
|
|
159 }
|
|
160
|
|
161 int main(int argc,char* argv[])
|
|
162 {
|
|
163 FILE* f;
|
|
164
|
|
165 if (argc != 2) {
|
|
166 fprintf(stderr, "Usage: %s <avi>\n", argv[0]);
|
|
167 exit(1);
|
|
168 }
|
|
169
|
15891
|
170 if (strcmp(argv[argc-1], "-") == 0) f=stdin;
|
|
171 else f=fopen(argv[argc-1],"rb");
|
15886
|
172
|
|
173 if (!f) {
|
|
174 fprintf(stderr, "Could not open '%s': %s\n",
|
|
175 argv[argc-1], strerror(errno));
|
|
176 exit(-errno);
|
|
177 }
|
|
178
|
|
179 dump(f);
|
|
180
|
|
181 return 0;
|
|
182 }
|
|
183
|