-
-
Save nekno/594cf46a8c58e32b382ffbca37a7fb4e to your computer and use it in GitHub Desktop.
thdmerge modded for stdin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _CRT_SECURE_NO_WARNINGS | |
#include <io.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <fcntl.h> | |
#include <sys/stat.h> | |
#include <errno.h> | |
void write_frame(unsigned char* buf, int len, int fd) | |
{ | |
int status; | |
if ((status = _write(fd, buf, len)) != len) | |
{ | |
switch (errno) | |
{ | |
case EBADF: | |
perror("Bad file descriptor!"); | |
break; | |
case ENOSPC: | |
perror("No space left on device!"); | |
break; | |
case EINVAL: | |
perror("Invalid parameter: buffer was NULL!"); | |
break; | |
default: | |
break; | |
} | |
} | |
} | |
int next_ac3(unsigned char *buf, int ac3_fd, int out_fd) | |
{ | |
int fsize; | |
if (_eof(ac3_fd)) | |
return -1; | |
// Determine the frame size to write. | |
if (_read(ac3_fd, buf, 8) != 8) | |
return -1; | |
switch (buf[4] & 0b00111110) | |
{ | |
case 0b001000: | |
fsize = 2 * 128; | |
break; | |
case 0b001010: | |
fsize = 2 * 160; | |
break; | |
case 0b001100: | |
fsize = 2 * 192; | |
break; | |
case 0b001110: | |
fsize = 2 * 224; | |
break; | |
case 0b010000: | |
fsize = 2 * 256; | |
break; | |
case 0b010010: | |
fsize = 2 * 320; | |
break; | |
case 0b010100: | |
fsize = 2 * 384; | |
break; | |
case 0b010110: | |
fsize = 2 * 448; | |
break; | |
case 0b011000: | |
fsize = 2 * 512; | |
break; | |
case 0b011010: | |
fsize = 2 * 640; | |
break; | |
case 0b011100: | |
fsize = 2 * 768; | |
break; | |
case 0b011110: | |
fsize = 2 * 896; | |
break; | |
case 0b100000: | |
fsize = 2 * 1024; | |
break; | |
case 0b100010: | |
fsize = 2 * 1152; | |
break; | |
case 0b100100: | |
fsize = 2 * 1280; | |
break; | |
default: | |
return -1; | |
} | |
// Write the frame. | |
if (_lseeki64(ac3_fd, -8, SEEK_CUR) == -1L) | |
return -1; | |
if (_read(ac3_fd, buf, fsize) != fsize) | |
return -1; | |
write_frame(buf, fsize, out_fd); | |
return 0; | |
} | |
int next_truehd(unsigned char *buf, int truehd_fd, int out_fd) | |
{ | |
int length, bytes_read = 0, total_bytes = 0, header_size = 8; | |
// Determine the frame size to write. | |
while (total_bytes < header_size) | |
{ | |
bytes_read = _read(truehd_fd, &buf[total_bytes], header_size-total_bytes); | |
//printf("Header bytes read: %d\n", bytes_read); | |
if (bytes_read == 0) | |
return -1; | |
total_bytes += bytes_read; | |
} | |
length = (2 * (((buf[0] << 8) | (buf[1])) & 0xfff)); | |
//printf("Length: %d\n", length); | |
// Write the frame. | |
while (total_bytes < length) | |
{ | |
bytes_read = _read(truehd_fd, &buf[total_bytes], length-total_bytes); | |
//printf("Bytes read: %d\n", bytes_read); | |
if (bytes_read == 0) | |
return -1; | |
total_bytes += bytes_read; | |
} | |
write_frame(buf, length, out_fd); | |
return 0; | |
} | |
void print_usage() | |
{ | |
printf("thdmerge 1.1+ by Donald A. Graft, modded by nekno\n"); | |
printf("Usage: thdmerge [-thd thd_file] -ac3 ac3_file -o output_file [-t]\n"); | |
printf("-thd: path to the TrueHD file; if omitted, the TrueHD stream can be provided on standard input\n"); | |
printf("-ac3: path to the AC3 file\n"); | |
printf("-o : path to the interleaved .thd+ac3 output file\n"); | |
printf("-t : truncate longer stream to length of shorter stream\n"); | |
exit(0); | |
} | |
int main(int argc, char** argv) | |
{ | |
unsigned char *buf; | |
double truehd_time, ac3_time; | |
int stdin_fd = -1, truehd_fd = -1, ac3_fd = -1, out_fd = -1; | |
int ac3_eof, truehd_eof; | |
int truncate = 0; | |
int arg; | |
if (argc < 5 || argc > 8) | |
print_usage(); | |
for (arg = 1; arg < argc; arg++) | |
{ | |
if (strcmp(argv[arg], "-thd") == 0) | |
{ | |
truehd_fd = _open(argv[++arg], _O_BINARY); | |
if (truehd_fd == -1) | |
{ | |
printf("Cannot open TrueHD file\n"); | |
exit(0); | |
} | |
} | |
else if (strcmp(argv[arg], "-ac3") == 0) | |
{ | |
ac3_fd = _open(argv[++arg], _O_BINARY); | |
if (ac3_fd == -1) | |
{ | |
printf("Cannot open AC3 file\n"); | |
exit(0); | |
} | |
} | |
else if (strcmp(argv[arg], "-o") == 0) | |
{ | |
_unlink(argv[++arg]); | |
out_fd = _open(argv[arg], _O_WRONLY | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE); | |
if (out_fd == -1) | |
{ | |
printf("Cannot open output file\n"); | |
exit(0); | |
} | |
} | |
else if (strcmp(argv[arg], "-t") == 0) | |
{ | |
truncate = 1; | |
} | |
} | |
if (truehd_fd == -1) | |
{ | |
freopen(NULL, "rb", stdin); | |
stdin_fd = _fileno(stdin); | |
if (_setmode(stdin_fd, _O_BINARY) == -1) | |
{ | |
printf("thdmerge: could not read standard input in binary mode\n"); | |
exit(1); | |
} | |
truehd_fd = stdin_fd; | |
printf("Reading TrueHD stream from standard input\n"); | |
} | |
if (ac3_fd == -1 || out_fd == -1) | |
print_usage(); | |
buf = (unsigned char*)malloc(1024 * 1024); | |
if (buf == NULL) | |
{ | |
printf("thdmerge: could not allocate memory\n"); | |
exit(1); | |
} | |
ac3_time = truehd_time = 0; | |
ac3_eof = truehd_eof = 0; | |
// Interleave keeping sync. | |
// Keep going until both streams hit EOF. | |
while (1) | |
{ | |
if (ac3_eof && truehd_eof) | |
break; | |
if (!ac3_eof && (truehd_eof || ac3_time <= truehd_time)) | |
{ | |
if (next_ac3(buf, ac3_fd, out_fd) == -1) | |
{ | |
ac3_eof = 1; | |
if (truncate) | |
break; | |
} | |
else | |
ac3_time += 0.032f; | |
} | |
else | |
{ | |
if (next_truehd(buf, truehd_fd, out_fd) == -1) | |
{ | |
truehd_eof = 1; | |
if (truncate) | |
break; | |
} | |
else | |
truehd_time += 1.0f / 1200; | |
} | |
} | |
free(buf); | |
_close(truehd_fd); | |
_close(ac3_fd); | |
_close(out_fd); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment