mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-25 12:27:21 +00:00
Merged all SPU packets into one Matroska block. Durations are extracting from the SPU packet itself.
This commit is contained in:
parent
dbd36858fd
commit
3e3ed29a3e
@ -72,12 +72,73 @@ void vobsub_packetizer_c::set_headers() {
|
|||||||
track_entry->EnableLacing(false);
|
track_entry->EnableLacing(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vobsub_packetizer_c::extract_duration(unsigned char *data, int buf_size) {
|
||||||
|
const int lengths[7] = {0, 0, 0, 2, 2, 6, 4};
|
||||||
|
int i, next_ctrlblk, packet_size, data_size, t, len;
|
||||||
|
|
||||||
|
packet_size = (data[0] << 8) | data[1];
|
||||||
|
data_size = (data[2] << 8) | data[3];
|
||||||
|
next_ctrlblk = data_size;
|
||||||
|
|
||||||
|
do {
|
||||||
|
i = next_ctrlblk;
|
||||||
|
t = (data[i] << 8) | data[i + 1];
|
||||||
|
i += 2;
|
||||||
|
next_ctrlblk = (data[i] << 8) | data[i + 1];
|
||||||
|
i += 2;
|
||||||
|
|
||||||
|
if((next_ctrlblk > packet_size) || (next_ctrlblk < data_size))
|
||||||
|
mxerror(PFX "Inconsistent data in the SPU packets (next_ctrlblk: %d, "
|
||||||
|
"packet_size: %d, data_size: %d)\n", next_ctrlblk, packet_size,
|
||||||
|
data_size);
|
||||||
|
|
||||||
|
if (data[i] <= 0x06)
|
||||||
|
len = lengths[data[i]];
|
||||||
|
else
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
if ((i + len) > packet_size) {
|
||||||
|
mxwarn(PFX "Warning: Wrong subpicture parameter blockending (i: %d, "
|
||||||
|
"len: %d, packet_size: %d)\n", i, len, packet_size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (data[i] == 0x02)
|
||||||
|
return 1024 * t / 90;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
while ((i <= next_ctrlblk) && (i < packet_size));
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define deliver() deliver_packet(dst_buf, dst_size, timecode, duration);
|
||||||
|
int vobsub_packetizer_c::deliver_packet(unsigned char *buf, int size,
|
||||||
|
int64_t timecode,
|
||||||
|
int64_t default_duration) {
|
||||||
|
int64_t duration;
|
||||||
|
|
||||||
|
if ((buf == NULL) || (size == 0)) {
|
||||||
|
safefree(buf);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
duration = extract_duration(buf, size);
|
||||||
|
if (duration == -1) {
|
||||||
|
mxwarn(PFX "Could not extract the duration for a SPU packet.\n");
|
||||||
|
duration = default_duration;
|
||||||
|
}
|
||||||
|
add_packet(buf, size, timecode, duration, true);
|
||||||
|
safefree(buf);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Adopted from mplayer's vobsub.c
|
// Adopted from mplayer's vobsub.c
|
||||||
int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
||||||
int64_t timecode, int64_t duration,
|
int64_t timecode, int64_t duration,
|
||||||
int64_t, int64_t) {
|
int64_t, int64_t) {
|
||||||
unsigned char *data;
|
unsigned char *dst_buf;
|
||||||
uint32_t len, idx, version, packet_size;
|
uint32_t len, idx, version, packet_size, dst_size;
|
||||||
int c, aid;
|
int c, aid;
|
||||||
float pts;
|
float pts;
|
||||||
/* Goto start of a packet, it starts with 0x000001?? */
|
/* Goto start of a packet, it starts with 0x000001?? */
|
||||||
@ -89,26 +150,28 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
|||||||
if (extract_from_mpeg) {
|
if (extract_from_mpeg) {
|
||||||
mm_mem_io_c in(srcbuf, size);
|
mm_mem_io_c in(srcbuf, size);
|
||||||
|
|
||||||
|
dst_buf = NULL;
|
||||||
|
dst_size = 0;
|
||||||
packet_size = 0;
|
packet_size = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (in.read(buf, 4) != 4)
|
if (in.read(buf, 4) != 4)
|
||||||
return -1;
|
return deliver();
|
||||||
while (memcmp(buf, wanted, sizeof(wanted)) != 0) {
|
while (memcmp(buf, wanted, sizeof(wanted)) != 0) {
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
memmove(buf, buf + 1, 3);
|
memmove(buf, buf + 1, 3);
|
||||||
buf[3] = c;
|
buf[3] = c;
|
||||||
}
|
}
|
||||||
switch (buf[3]) {
|
switch (buf[3]) {
|
||||||
case 0xb9: /* System End Code */
|
case 0xb9: /* System End Code */
|
||||||
return 0;
|
return deliver();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xba: /* Packet start code */
|
case 0xba: /* Packet start code */
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
if ((c & 0xc0) == 0x40)
|
if ((c & 0xc0) == 0x40)
|
||||||
version = 4;
|
version = 4;
|
||||||
else if ((c & 0xf0) == 0x20)
|
else if ((c & 0xf0) == 0x20)
|
||||||
@ -116,33 +179,33 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
|||||||
else {
|
else {
|
||||||
mxwarn(PFX "Unsupported MPEG version: 0x%02x in packet %lld\n", c,
|
mxwarn(PFX "Unsupported MPEG version: 0x%02x in packet %lld\n", c,
|
||||||
packet_num);
|
packet_num);
|
||||||
return -1;
|
return deliver();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == 4) {
|
if (version == 4) {
|
||||||
if (!in.setFilePointer2(9, seek_current))
|
if (!in.setFilePointer2(9, seek_current))
|
||||||
return -1;
|
return deliver();
|
||||||
} else if (version == 2) {
|
} else if (version == 2) {
|
||||||
if (!in.setFilePointer2(7, seek_current))
|
if (!in.setFilePointer2(7, seek_current))
|
||||||
return -1;
|
return deliver();
|
||||||
} else
|
} else
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xbd: /* packet */
|
case 0xbd: /* packet */
|
||||||
if (in.read(buf, 2) != 2)
|
if (in.read(buf, 2) != 2)
|
||||||
return -1;
|
return deliver();
|
||||||
len = buf[0] << 8 | buf[1];
|
len = buf[0] << 8 | buf[1];
|
||||||
idx = in.getFilePointer();
|
idx = in.getFilePointer();
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
if ((c & 0xC0) == 0x40) { /* skip STD scale & size */
|
if ((c & 0xC0) == 0x40) { /* skip STD scale & size */
|
||||||
if (in.getch() < 0)
|
if (in.getch() < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
}
|
}
|
||||||
if ((c & 0xf0) == 0x20) { /* System-1 stream timestamp */
|
if ((c & 0xf0) == 0x20) { /* System-1 stream timestamp */
|
||||||
/* Do we need this? */
|
/* Do we need this? */
|
||||||
@ -154,21 +217,21 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
|||||||
uint32_t pts_flags, hdrlen, dataidx;
|
uint32_t pts_flags, hdrlen, dataidx;
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
pts_flags = c;
|
pts_flags = c;
|
||||||
c = in.getch();
|
c = in.getch();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
return -1;
|
return deliver();
|
||||||
hdrlen = c;
|
hdrlen = c;
|
||||||
dataidx = in.getFilePointer() + hdrlen;
|
dataidx = in.getFilePointer() + hdrlen;
|
||||||
if (dataidx > idx + len) {
|
if (dataidx > idx + len) {
|
||||||
mxwarn(PFX "Invalid header length: %d (total length: %d, "
|
mxwarn(PFX "Invalid header length: %d (total length: %d, "
|
||||||
"idx: %d, dataidx: %d)\n", hdrlen, len, idx, dataidx);
|
"idx: %d, dataidx: %d)\n", hdrlen, len, idx, dataidx);
|
||||||
return -1;
|
return deliver();
|
||||||
}
|
}
|
||||||
if ((pts_flags & 0xc0) == 0x80) {
|
if ((pts_flags & 0xc0) == 0x80) {
|
||||||
if (in.read(buf, 5) != 5)
|
if (in.read(buf, 5) != 5)
|
||||||
return -1;
|
return deliver();
|
||||||
if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) &&
|
if (!(((buf[0] & 0xf0) == 0x20) && (buf[0] & 1) &&
|
||||||
(buf[2] & 1) && (buf[4] & 1))) {
|
(buf[2] & 1) && (buf[4] & 1))) {
|
||||||
mxwarn(PFX "PTS error: 0x%02x %02x%02x %02x%02x \n",
|
mxwarn(PFX "PTS error: 0x%02x %02x%02x %02x%02x \n",
|
||||||
@ -185,20 +248,18 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
|||||||
aid = in.getch();
|
aid = in.getch();
|
||||||
if (aid < 0) {
|
if (aid < 0) {
|
||||||
mxwarn(PFX "Bogus aid %d\n", aid);
|
mxwarn(PFX "Bogus aid %d\n", aid);
|
||||||
return -1;
|
return deliver();
|
||||||
}
|
}
|
||||||
packet_size = len - ((unsigned int)in.getFilePointer() - idx);
|
packet_size = len - ((unsigned int)in.getFilePointer() - idx);
|
||||||
data = (unsigned char *)safemalloc(packet_size);
|
dst_buf = (unsigned char *)saferealloc(dst_buf, dst_size +
|
||||||
if (in.read(data, packet_size) != packet_size) {
|
packet_size);
|
||||||
|
if (in.read(&dst_buf[dst_size], packet_size) != packet_size) {
|
||||||
mxwarn(PFX "in.read failure");
|
mxwarn(PFX "in.read failure");
|
||||||
safefree(data);
|
return deliver();
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
dst_size += packet_size;
|
||||||
spu_size += packet_size;
|
spu_size += packet_size;
|
||||||
overhead += size - packet_size;
|
overhead += size - packet_size;
|
||||||
add_packet(data, packet_size, timecode, duration, true);
|
|
||||||
safefree(data);
|
|
||||||
|
|
||||||
idx = len;
|
idx = len;
|
||||||
}
|
}
|
||||||
@ -206,34 +267,34 @@ int vobsub_packetizer_c::process(unsigned char *srcbuf, int size,
|
|||||||
|
|
||||||
case 0xbe: /* Padding */
|
case 0xbe: /* Padding */
|
||||||
if (in.read(buf, 2) != 2)
|
if (in.read(buf, 2) != 2)
|
||||||
return -1;
|
return deliver();
|
||||||
len = buf[0] << 8 | buf[1];
|
len = buf[0] << 8 | buf[1];
|
||||||
if ((len > 0) && !in.setFilePointer2(len, seek_current))
|
if ((len > 0) && !in.setFilePointer2(len, seek_current))
|
||||||
return -1;
|
return deliver();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((0xc0 <= buf[3]) && (buf[3] < 0xf0)) {
|
if ((0xc0 <= buf[3]) && (buf[3] < 0xf0)) {
|
||||||
/* MPEG audio or video */
|
/* MPEG audio or video */
|
||||||
if (in.read(buf, 2) != 2)
|
if (in.read(buf, 2) != 2)
|
||||||
return -1;
|
return deliver();
|
||||||
len = (buf[0] << 8) | buf[1];
|
len = (buf[0] << 8) | buf[1];
|
||||||
if ((len > 0) && !in.setFilePointer2(len, seek_current))
|
if ((len > 0) && !in.setFilePointer2(len, seek_current))
|
||||||
return -1;
|
return deliver();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mxwarn(PFX "unknown header 0x%02X%02X%02X%02X\n", buf[0], buf[1],
|
mxwarn(PFX "unknown header 0x%02X%02X%02X%02X\n", buf[0], buf[1],
|
||||||
buf[2], buf[3]);
|
buf[2], buf[3]);
|
||||||
return -1;
|
return deliver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EMOREDATA;
|
return deliver();
|
||||||
}
|
}
|
||||||
|
|
||||||
spu_size += size;
|
spu_size += size;
|
||||||
add_packet(buf, size, timecode, duration, true);
|
add_packet(srcbuf, size, timecode, duration, true);
|
||||||
|
|
||||||
return EMOREDATA;
|
return EMOREDATA;
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,11 @@ public:
|
|||||||
virtual void set_headers();
|
virtual void set_headers();
|
||||||
|
|
||||||
virtual void dump_debug_info();
|
virtual void dump_debug_info();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual int extract_duration(unsigned char *data, int buf_size);
|
||||||
|
virtual int deliver_packet(unsigned char *buf, int size, int64_t timecode,
|
||||||
|
int64_t default_duration);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __P_VOBSUB_H
|
#endif // __P_VOBSUB_H
|
||||||
|
Loading…
Reference in New Issue
Block a user