/* * Extract * Copyright (C) 2013 Adam Williams * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #define _LARGEFILE_SOURCE 1 #define _LARGEFILE64_SOURCE 1 #define _FILE_OFFSET_BITS 64 #include #include #include #include #define BUFFER_SIZE 0x2000000 int64_t get_number(char *text) { int64_t result; if(text[0] == '0' && text[1] == 'x') { sscanf(text, "%llx", &result); } else { sscanf(text, "%lld", &result); } return result; } int main(int argc, char *argv[]) { int is_bd = 0; int buffer_size = BUFFER_SIZE; int64_t i; int64_t start = -1; int64_t end = -1; int64_t output_position = 0; char *filename = 0; int use_stdin = 0; for(i = 1; i < argc; i++) { if(!strcmp(argv[i], "-b")) { is_bd = 1; buffer_size = (BUFFER_SIZE / 2048 / 3) * 2048 * 3; } else if(!filename) { filename = argv[i]; if(!strcmp(filename, "-")) use_stdin = 1; } else if(start < 0) { start = get_number(argv[i]); } else if(end < 0) { end = get_number(argv[i]); } } if(!filename || start < 0) { fprintf(stderr, "Usage: extract [-b] filename [end]\n" "-b extract transport stream from Blu-Ray stream.\n" "Specify - as filename to read from stdin.\n" "Start and end may be decimal or prefixed by 0x for hex.\n" "Omit the end position to read forever.\n"); exit(1); } FILE *file = 0; if(use_stdin) { file = stdin; } else { file = fopen64(filename, "r"); if(!file) { perror("fopen"); exit(1); } } unsigned char *buffer = malloc(buffer_size); fprintf(stderr, "Extracting %s from %lld (%llx) to ", filename, start, start); if(end < 0) fprintf(stderr, "infinity.\n"); else fprintf(stderr, "%lld (%llx)\n", end, end); if(is_bd) fprintf(stderr, "Stripping Blu-Ray headers.\n"); if(!use_stdin) { fseeko64(file, start, SEEK_SET); } else { for(i = 0; i < start; i++) fgetc(file); } i = start; while(1) { int fragment_size = buffer_size; if(end > 0 && i + fragment_size > end) fragment_size = end - i; fprintf(stderr, "Reading from %llx \r", i); fflush(stdout); int bytes_read = fread(buffer, 1, fragment_size, file); int output_size = bytes_read; // Strip Blu-Ray headers if(is_bd) { int j, k; output_size = 0; for(j = 4, k = 0; j < fragment_size; j += 192, k += 188) { if(buffer[j] != 0x47) fprintf(stderr, "Invalid start code\n"); memcpy(buffer + k, buffer + j, 188); output_size += 188; } } fprintf(stderr, "Writing to %llx \r", output_position); fflush(stdout); fwrite(buffer, output_size, 1, stdout); output_position += output_size; i += buffer_size; if(end > 0 && i >= end) break; if(end < 0 && bytes_read < fragment_size) break; } if(!use_stdin) fclose(file); }