Pad MPEG packets up to 2048 bytes for VobSub extraction because some programs depend on it. Patch by Mike Matsnev <mike () po !cs ! msu ! su>

This commit is contained in:
Moritz Bunkus 2005-05-17 17:39:00 +00:00
parent 596d11ae2f
commit 0a3f88b6d7
2 changed files with 63 additions and 10 deletions

View File

@ -1,3 +1,9 @@
2005-05-17 Moritz Bunkus <moritz@bunkus.org>
* mkvextract: bug fix: The MPEG packets are now padded to 2048
byte boundaries as some programs require them to be. Patch by
Mike Matsnev (see AUTHORS).
2005-05-07 Moritz Bunkus <moritz@bunkus.org>
* mkvinfo: bug fix: Removed the restriction of max. ten levels of

View File

@ -124,6 +124,8 @@ xtr_vobsub_c::handle_block(KaxBlock &block,
int64_t duration,
int64_t bref,
int64_t fref) {
static unsigned char padding_data[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff};
mpeg_es_header_t es;
mpeg_ps_header_t ps;
uint64_t c;
@ -138,7 +140,7 @@ xtr_vobsub_c::handle_block(KaxBlock &block,
for (i = 0; i < block.NumberFrames(); i++) {
autofree_ptr<unsigned char> af_data;
unsigned char *data;
uint32_t size;
uint32_t size, padding, first;
DataBuffer &data_buffer = block.GetBuffer(i);
size = data_buffer.Size();
@ -146,6 +148,15 @@ xtr_vobsub_c::handle_block(KaxBlock &block,
if (content_decoder.reverse(data, size, CONTENT_ENCODING_SCOPE_BLOCK))
af_data.set(data);
positions.push_back(vmaster->out->getFilePointer());
timecodes.push_back(timecode);
padding = (2048 - (size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t))) & 2047;
first = size + sizeof(mpeg_ps_header_t) +
sizeof(mpeg_es_header_t) > 2048 ?
2048 - sizeof(mpeg_ps_header_t) - sizeof(mpeg_es_header_t) : size;
memset(&ps, 0, sizeof(mpeg_ps_header_t));
ps.pfx[2] = 0x01;
@ -155,25 +166,27 @@ xtr_vobsub_c::handle_block(KaxBlock &block,
ps.scr[0] = 0x40 | ((uint8_t)(c >> 27) & 0x38) | 0x04 |
((uint8_t)(c >> 28) & 0x03);
ps.scr[1] = (uint8_t)(c >> 20);
ps.scr[2] = ((uint8_t)(c >> 12) & 0xf8) | 0x40 |
((uint8_t)(c >> 13) & 0x07);
ps.scr[2] = ((uint8_t)(c >> 12) & 0xf8) | 0x04 |
((uint8_t)(c >> 13) & 0x03);
ps.scr[3] = (uint8_t)(c >> 5);
ps.scr[4] = ((uint8_t)(c << 3) & 0xf8) | 0x40;
ps.scr[4] = ((uint8_t)(c << 3) & 0xf8) | 0x04;
ps.scr[5] = 1;
ps.muxr[0] = 1;
ps.muxr[1] = 0x89;
ps.muxr[2] = 0xc3; // just some value
ps.stlen = 0xf8;
if ((padding < 8) && (first == size))
ps.stlen |= (uint8_t)padding;
memset(&es, 0, sizeof(mpeg_es_header_t));
es.pfx[2] = 1;
es.stream_id = 0xbd;
es.len[0] = ((size + 9) >> 8) & 0xff;
es.len[1] = (size + 9) & 0xff;
es.len[0] = (uint8_t)((first + 9) >> 8);
es.len[1] = (uint8_t)(first + 9);
es.flags[0] = 0x81;
es.flags[1] = 0x80;
es.hlen = 5;
es.pts[0] = 0x20 | ((uint8_t)(c >> 29) & 0xe0) | 0x01;
es.pts[0] = 0x20 | ((uint8_t)(c >> 29) & 0x0e) | 0x01;
es.pts[1] = (uint8_t)(c >> 22);
es.pts[2] = ((uint8_t)(c >> 14) & 0xfe) | 0x01;
es.pts[3] = (uint8_t)(c >> 7);
@ -183,11 +196,45 @@ xtr_vobsub_c::handle_block(KaxBlock &block,
else
es.lidx = stream_id;
positions.push_back(vmaster->out->getFilePointer());
timecodes.push_back(timecode);
vmaster->out->write(&ps, sizeof(mpeg_ps_header_t));
if ((padding > 0) && (padding < 8) && (first == size))
vmaster->out->write(padding_data, padding);
vmaster->out->write(&es, sizeof(mpeg_es_header_t));
vmaster->out->write(data, size);
vmaster->out->write(data, first);
while (first < size) {
size -= first;
data += first;
padding = (2048 - (size + 10 + sizeof(mpeg_ps_header_t))) & 2047;
first = size + 10 + sizeof(mpeg_ps_header_t) > 2048 ?
2048 - 10 - sizeof(mpeg_ps_header_t) : size;
if ((padding < 8) && (first == size))
ps.stlen |= (uint8_t)padding;
es.len[0] = (uint8_t)((first + 4) >> 8);
es.len[1] = (uint8_t)(first + 4);
es.flags[1] = 0;
es.hlen = 0;
es.pts[0] = es.lidx;
vmaster->out->write(&ps, sizeof(mpeg_ps_header_t));
if ((padding > 0) && (padding < 8) && (first == size))
vmaster->out->write(padding_data, padding);
vmaster->out->write(&es, 10);
vmaster->out->write(data, first);
}
if (8 <= padding) {
padding -= 6;
es.stream_id = 0xbe;
es.len[0] = (uint8_t)(padding >> 8);
es.len[1] = (uint8_t)padding;
vmaster->out->write(&es, 6); // XXX
while (0 < padding) {
uint32_t todo = padding > 8 ? 8 : padding;
vmaster->out->write(padding_data, todo);
padding -= todo;
}
}
}
}