1 /* Copyright (C) 2009 Anders Holst
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #define _LARGEFILE64_SOURCE
15 #include <sys/types.h>
29 char* makefilename(const char* dir, const char* base, const char* ext, const char* post)
33 len1 = (dir ? strlen(dir) : 0);
34 len2 = (base ? strlen(base) : 0);
35 len3 = (ext ? strlen(ext) : 0);
38 if (buf[len1-1] != '/') {
44 strcpy(buf+len1, base);
45 if (ext && len2>=len3 && !strcmp(base+len2-len3,ext))
48 strcpy(buf+len1+len2, ext);
50 strcpy(buf+len1+len2+len3, post);
54 int writebufinternal(int f, off64_t sz, off64_t tm)
57 buf[0] = (off64_t)bswap_64((unsigned long long int)sz);
58 buf[1] = (off64_t)bswap_64((unsigned long long int)tm);
59 if (write(f, buf, 16) != 16)
65 int framepid(unsigned char* buf, int pos)
67 return ((buf[pos+1] & 0x1f) << 8) + buf[pos+2];
70 off64_t framepts(unsigned char* buf, int pos)
72 int tmp = (buf[pos+3] & 0x20 ? pos+buf[pos+4]+5 : pos+4);
74 if (buf[pos+1] & 0x40 &&
76 buf[tmp]==0 && buf[tmp+1]==0 && buf[tmp+2]==1 &&
78 pts = ((unsigned long long)(buf[tmp+9]&0xE)) << 29;
79 pts |= ((unsigned long long)(buf[tmp+10]&0xFF)) << 22;
80 pts |= ((unsigned long long)(buf[tmp+11]&0xFE)) << 14;
81 pts |= ((unsigned long long)(buf[tmp+12]&0xFF)) << 7;
82 pts |= ((unsigned long long)(buf[tmp+13]&0xFE)) >> 1;
88 int framesearch(int fts, int first, off64_t& retpos, off64_t& retpts, off64_t& retpos2, off64_t& retdat)
90 static unsigned char buf[LEN];
92 static off64_t pos = -1;
96 static int sdflag = 0;
98 if (pos == -1 || first) {
99 num = read(fts, buf, LEN);
109 for (; p < buf+num-6; p++)
110 if (p[0]==0 && p[1]==0 && p[2]==1) {
111 ind = ((p - buf)/188)*188;
112 if ((p[3] & 0xf0) == 0xe0 && (buf[ind+1] & 0x40) &&
113 (p-buf)-ind == (buf[ind+3] & 0x20 ? buf[ind+4] + 5 : 4)) {
114 pid = framepid(buf, ind);
115 } else if (pid != -1 && pid != framepid(buf, ind)) {
119 if (p[3]==0 || p[3]==0xb3 || p[3]==0xb8) { // MPEG2
121 retpts = framepts(buf, ind);
127 retdat = (unsigned int) p[3] | (p[4]<<8) | (p[5]<<16) | (p[6]<<24);
128 retpos2 = pos + (p - buf);
129 st = (p - buf) - ind + 1;
132 } else if (!sdflag && p[3]==0x09 && (buf[ind+1] & 0x40)) { // H264
133 if ((p[4] >> 5)==0) {
134 retpts = framepts(buf, ind);
140 retdat = p[3] | (p[4]<<8);
141 retpos2 = pos + (p - buf);
142 st = (p - buf) - ind + 1;
150 sdflag = 0; // reset to get some fault tolerance
153 num = read(fts, buf, LEN);
171 int do_one(int fts, int fap, int fsc)
178 while (framesearch(fts, first, pos, pts, pos2, dat) >= 0) {
180 if (pos >= 0 && pts >= 0)
181 if (fap >= 0 && writebufinternal(fap, pos, pts))
183 if (fsc >= 0 && writebufinternal(fsc, pos2, dat))
189 int do_movie(char* inname)
191 int f_ts=-1, f_sc=-1, f_ap=-1, f_tmp=-1;
193 tmpname = makefilename(0, inname, ".ts", 0);
194 f_ts = open(tmpname, O_RDONLY | O_LARGEFILE);
196 printf("Failed to open input stream file \"%s\"\n", tmpname);
199 tmpname = makefilename(0, inname, ".ts", ".reconstruct_apsc");
200 f_tmp = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
202 printf("Failed to open sentry file \"%s\"\n", tmpname);
206 tmpname = makefilename(0, inname, ".ts", ".ap");
207 f_ap = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
209 printf("Failed to open output .ap file \"%s\"\n", tmpname);
212 tmpname = makefilename(0, inname, ".ts", ".sc");
213 f_sc = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
215 printf("Failed to open output .sc file \"%s\"\n", tmpname);
219 printf(" Processing .ap and .sc of \"%s\" ... ", inname);
221 if (do_one(f_ts, f_ap, f_sc)) {
222 printf("\nFailed to reconstruct files for \"%s\"\n", inname);
230 unlink(makefilename(0, inname, ".ts", ".reconstruct_apsc"));
237 unlink(makefilename(0, inname, ".ts", ".ap"));
241 unlink(makefilename(0, inname, ".ts", ".sc"));
243 unlink(makefilename(0, inname, ".ts", ".reconstruct_apsc"));
247 int do_directory(char* dirname)
249 int f_ts, f_sc, f_ap, f_tmp;
251 char *inname, *tmpname;
252 DIR* dir = opendir(dirname);
256 while ((entry = readdir(dir))) {
257 inname = entry->d_name;
258 if (strlen(inname) > 3 && !strcmp(inname + strlen(inname) - 3, ".ts")) {
259 tmpname = makefilename(dirname, inname, ".ts", ".reconstruct_apsc");
261 if (stat(tmpname, &statbuf) != -1)
264 tmpname = makefilename(dirname, inname, ".ts", ".ap");
266 do_ap = (stat(tmpname, &statbuf) == -1 && errno == ENOENT);
267 tmpname = makefilename(dirname, inname, ".ts", ".sc");
269 do_sc = (stat(tmpname, &statbuf) == -1 && errno == ENOENT);
271 if (do_ap || do_sc) {
272 f_ts=-1, f_sc=-1, f_ap=-1, f_tmp=-1;
273 tmpname = makefilename(dirname, inname, ".ts", 0);
274 f_ts = open(tmpname, O_RDONLY | O_LARGEFILE);
276 printf("Failed to open input stream file \"%s\"\n", tmpname);
279 tmpname = makefilename(dirname, inname, ".ts", ".reconstruct_apsc");
280 f_tmp = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
282 printf("Failed to open sentry file \"%s\"\n", tmpname);
287 tmpname = makefilename(dirname, inname, ".ts", ".ap");
288 f_ap = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
290 printf("Failed to open output .ap file \"%s\"\n", tmpname);
296 tmpname = makefilename(dirname, inname, ".ts", ".sc");
297 f_sc = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
299 printf("Failed to open output .sc file \"%s\"\n", tmpname);
305 printf(" Processing %s of \"%s\" ... ", (do_ap ? (do_sc ? ".ap and .sc" : ".ap") : ".sc"), inname);
307 if (do_one(f_ts, f_ap, f_sc)) {
308 printf("\nFailed to reconstruct files for \"%s\"\n", inname);
312 unlink(makefilename(dirname, inname, ".ts", ".ap"));
316 unlink(makefilename(dirname, inname, ".ts", ".sc"));
318 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
326 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
332 printf("Failed to open directory \"%s\"\n", dirname);
342 unlink(makefilename(dirname, inname, ".ts", ".ap"));
346 unlink(makefilename(dirname, inname, ".ts", ".sc"));
348 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
352 int main(int argc, char* argv[])
354 if (argc == 2 && *argv[1] != '-') {
355 if (do_movie(argv[1]))
357 } else if (argc == 3 && !strcmp(argv[1], "-d")) {
358 if (do_directory(argv[2]))
361 printf("Usage: reconstruct_apsc movie_file\n");
362 printf(" reconstruct_apsc -d movie_directory\n");