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