Merged all SPU packets into one Matroska block. Durations are extracting from the SPU packet itself.

This commit is contained in:
Moritz Bunkus 2003-11-02 15:50:57 +00:00
parent dbd36858fd
commit 3e3ed29a3e
2 changed files with 98 additions and 32 deletions

View File

@ -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;
} }

View File

@ -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