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);
107 for (; p < buf+num-6; p++)
108 if (p[0]==0 && p[1]==0 && p[2]==1) {
109 ind = ((p - buf)/188)*188;
110 if ((p[3] & 0xf0) == 0xe0 && (buf[ind+1] & 0x40) &&
111 (p-buf)-ind == (buf[ind+3] & 0x20 ? buf[ind+4] + 5 : 4)) {
112 pid = framepid(buf, ind);
113 } else if (pid != -1 && pid != framepid(buf, ind)) {
117 if (p[3]==0 || p[3]==0xb3 || p[3]==0xb8) { // MPEG2
118 if (p[3]==0 && ((p[5] >> 3 & 7) == 1)) {
119 retpts = framepts(buf, ind);
125 retdat = (unsigned int) p[3] | (p[4]<<8) | (p[5]<<16) | (p[6]<<24);
126 retpos2 = pos + (p - buf);
127 st = (p - buf) - ind + 1;
130 } else if (!sdflag && p[3]==0x09 && (buf[ind+1] & 0x40)) { // H264
131 if ((p[4] >> 5)==0) {
132 retpts = framepts(buf, ind);
138 retdat = p[3] | (p[4]<<8);
139 retpos2 = pos + (p - buf);
140 st = (p - buf) - ind + 1;
148 sdflag = 0; // reset to get some fault tolerance
151 num = read(fts, buf, LEN);
169 int do_one(int fts, int fap, int fsc)
176 while (framesearch(fts, first, pos, pts, pos2, dat) >= 0) {
179 if (fap >= 0 && writebufinternal(fap, pos, pts))
181 if (fsc >= 0 && writebufinternal(fsc, pos2, dat))
187 int do_movie(char* inname)
189 int f_ts=-1, f_sc=-1, f_ap=-1, f_tmp=-1;
191 tmpname = makefilename(0, inname, ".ts", 0);
192 f_ts = open(tmpname, O_RDONLY | O_LARGEFILE);
194 printf("Failed to open input stream file \"%s\"\n", tmpname);
197 tmpname = makefilename(0, inname, ".ts", ".reconstruct_apsc");
198 f_tmp = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
200 printf("Failed to open sentry file \"%s\"\n", tmpname);
204 tmpname = makefilename(0, inname, ".ts", ".ap");
205 f_ap = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
207 printf("Failed to open output .ap file \"%s\"\n", tmpname);
210 tmpname = makefilename(0, inname, ".ts", ".sc");
211 f_sc = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
213 printf("Failed to open output .sc file \"%s\"\n", tmpname);
217 printf(" Processing .ap and .sc of \"%s\" ... ", inname);
219 if (do_one(f_ts, f_ap, f_sc)) {
220 printf("\nFailed to reconstruct files for \"%s\"\n", inname);
228 unlink(makefilename(0, inname, ".ts", ".reconstruct_apsc"));
235 unlink(makefilename(0, inname, ".ts", ".ap"));
239 unlink(makefilename(0, inname, ".ts", ".sc"));
241 unlink(makefilename(0, inname, ".ts", ".reconstruct_apsc"));
245 int do_directory(char* dirname)
247 int f_ts, f_sc, f_ap, f_tmp;
249 char *inname, *tmpname;
250 DIR* dir = opendir(dirname);
254 while ((entry = readdir(dir))) {
255 inname = entry->d_name;
256 if (strlen(inname) > 3 && !strcmp(inname + strlen(inname) - 3, ".ts")) {
257 tmpname = makefilename(dirname, inname, ".ts", ".reconstruct_apsc");
259 if (stat(tmpname, &statbuf) != -1)
262 tmpname = makefilename(dirname, inname, ".ts", ".ap");
264 do_ap = (stat(tmpname, &statbuf) == -1 && errno == ENOENT);
265 tmpname = makefilename(dirname, inname, ".ts", ".sc");
267 do_sc = (stat(tmpname, &statbuf) == -1 && errno == ENOENT);
269 if (do_ap || do_sc) {
270 f_ts=-1, f_sc=-1, f_ap=-1, f_tmp=-1;
271 tmpname = makefilename(dirname, inname, ".ts", 0);
272 f_ts = open(tmpname, O_RDONLY | O_LARGEFILE);
274 printf("Failed to open input stream file \"%s\"\n", tmpname);
277 tmpname = makefilename(dirname, inname, ".ts", ".reconstruct_apsc");
278 f_tmp = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
280 printf("Failed to open sentry file \"%s\"\n", tmpname);
285 tmpname = makefilename(dirname, inname, ".ts", ".ap");
286 f_ap = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
288 printf("Failed to open output .ap file \"%s\"\n", tmpname);
294 tmpname = makefilename(dirname, inname, ".ts", ".sc");
295 f_sc = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0x1a4);
297 printf("Failed to open output .sc file \"%s\"\n", tmpname);
303 printf(" Processing %s of \"%s\" ... ", (do_ap ? (do_sc ? ".ap and .sc" : ".ap") : ".sc"), inname);
305 if (do_one(f_ts, f_ap, f_sc)) {
306 printf("\nFailed to reconstruct files for \"%s\"\n", inname);
310 unlink(makefilename(dirname, inname, ".ts", ".ap"));
314 unlink(makefilename(dirname, inname, ".ts", ".sc"));
316 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
324 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
330 printf("Failed to open directory \"%s\"\n", dirname);
340 unlink(makefilename(dirname, inname, ".ts", ".ap"));
344 unlink(makefilename(dirname, inname, ".ts", ".sc"));
346 unlink(makefilename(dirname, inname, ".ts", ".reconstruct_apsc"));
350 int main(int argc, char* argv[])
352 if (argc == 2 && *argv[1] != '-') {
353 if (do_movie(argv[1]))
355 } else if (argc == 3 && !strcmp(argv[1], "-d")) {
356 if (do_directory(argv[2]))
359 printf("Usage: reconstruct_apsc movie_file\n");
360 printf(" reconstruct_apsc -d movie_directory\n");