So, I slightly modified Windows version of thdmerge.
in theory it should prepare thd (trueHD) file for blu-ray muxing.
make file.thd and file.ac3 with ffmpeg
$ ffmpeg -i ~/vid_20210526.mp4 -vn -c:a ac3 b.ac3
$ ffmpeg -i ~/vid_20210526.mp4 -vn -c:a truehd -strict -2 a.thd
compile
gcc -o thdmerge thdmerge.cpp
run
./thdmerge a.thd b.ac3 full.thd+ac3
try to mux this resulting file with tsmuxer
#define _CRT_SECURE_NO_WARNINGS
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
int eof(int fd)
{
unsigned char *buffer;
if (read(fd, buffer, 1) == 0)
return 1;
return 0;
}
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 (lseek64(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;
if (eof(truehd_fd))
return -1;
// Dtermine the frame size to write.
if (read(truehd_fd, buf, 8) != 8)
return -1;
length = 2 * (((buf[0] << 8) | (buf[1])) & 0xfff);
// Write the frame.
if (lseek64(truehd_fd, -8, SEEK_CUR) == -1L)
return -1;
if (read(truehd_fd, buf, length) != length)
return -1;
write_frame(buf, length, out_fd);
return 0;
}
int main(int argc, char** argv)
{
unsigned char *buf;
double truehd_time, ac3_time;
int truehd_fd, ac3_fd, out_fd;
int ac3_eof, truehd_eof;
int truncate;
if (argc == 1 || argc > 5)
{
printf("thdmerge 1.1 by Donald A. Graft\n");
printf("Usage: thdmerge thd_file ac3_file output_file [-t]\n");
printf("-t: truncate longer stream to length of shorter stream\n");
exit(0);
}
if (argc == 5)
truncate = 1;
else
truncate = 0;
buf = (unsigned char*)malloc(1024 * 1024);
if (buf == NULL)
{
printf("thdmerge: could not allocate memory\n");
exit(1);
}
truehd_fd = open(argv[1],O_RDONLY);
if (truehd_fd == -1)
{
printf("Cannot open TrueHD file\n");
exit(0);
}
ac3_fd = open(argv[2], O_RDONLY);
if (ac3_fd == -1)
{
printf("Cannot open AC3 file\n");
exit(0);
}
unlink(argv[3]);
out_fd = open(argv[3], O_WRONLY | O_CREAT , S_IREAD | S_IWRITE);
if (out_fd == -1)
{
printf("Cannot open output file\n");
exit(0);
}
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;
}
--
Cin mailing list
[email protected]
https://lists.cinelerra-gg.org/mailman/listinfo/cin