mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-24 11:54:01 +00:00
Detect and handle the absence of comment packets in non-native streams (aka "AVI compatibility mode streams").
This commit is contained in:
parent
f29ec94254
commit
ce0c8a6986
@ -1,3 +1,8 @@
|
||||
2004-05-31 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: Improved handling for OGM files. Streams that
|
||||
are lacking the comment packet are handled better.
|
||||
|
||||
2004-05-29 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: Some MP3 streams are padded in the front with
|
||||
|
@ -690,6 +690,16 @@ ogm_reader_c::packet_available() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ogm_reader_c::handle_new_stream_and_packets(ogg_page *og) {
|
||||
ogm_demuxer_t *dmx;
|
||||
|
||||
handle_new_stream(og);
|
||||
dmx = find_demuxer(ogg_page_serialno(og));
|
||||
if (dmx != NULL)
|
||||
process_header_packets(dmx);
|
||||
}
|
||||
|
||||
/*
|
||||
* The page is the beginning of a new stream. Check the contents for known
|
||||
* stream headers. If it is a known stream and the user has requested that
|
||||
@ -794,6 +804,7 @@ ogm_reader_c::handle_new_stream(ogg_page *og) {
|
||||
dmx->serial = ogg_page_serialno(og);
|
||||
memcpy(&dmx->os, &new_oss, sizeof(ogg_stream_state));
|
||||
dmx->sid = nvstreams;
|
||||
dmx->native_mode = false;
|
||||
add_new_demuxer(dmx);
|
||||
if (video_fps < 0)
|
||||
video_fps = 10000000.0 / (float)get_uint64(&sth->time_unit);
|
||||
@ -832,6 +843,7 @@ ogm_reader_c::handle_new_stream(ogg_page *og) {
|
||||
dmx->serial = ogg_page_serialno(og);
|
||||
memcpy(&dmx->os, &new_oss, sizeof(ogg_stream_state));
|
||||
dmx->sid = nastreams;
|
||||
dmx->native_mode = false;
|
||||
add_new_demuxer(dmx);
|
||||
|
||||
return;
|
||||
@ -850,6 +862,7 @@ ogm_reader_c::handle_new_stream(ogg_page *og) {
|
||||
dmx->serial = ogg_page_serialno(og);
|
||||
memcpy(&dmx->os, &new_oss, sizeof(ogg_stream_state));
|
||||
dmx->sid = ntstreams;
|
||||
dmx->native_mode = false;
|
||||
add_new_demuxer(dmx);
|
||||
|
||||
return;
|
||||
@ -880,10 +893,10 @@ void
|
||||
ogm_reader_c::process_page(ogg_page *og) {
|
||||
ogm_demuxer_t *dmx;
|
||||
ogg_packet op;
|
||||
int hdrlen, eos, i;
|
||||
long lenbytes;
|
||||
int duration_len, eos, i;
|
||||
long duration;
|
||||
|
||||
lenbytes = 0;
|
||||
duration = 0;
|
||||
dmx = find_demuxer(ogg_page_serialno(og));
|
||||
if (dmx == NULL)
|
||||
return;
|
||||
@ -891,6 +904,13 @@ ogm_reader_c::process_page(ogg_page *og) {
|
||||
debug_enter("ogm_reader_c::process_page");
|
||||
|
||||
ogg_stream_pagein(&dmx->os, og);
|
||||
if (dmx->skip_first_data_page) {
|
||||
while (ogg_stream_packetout(&dmx->os, &op) == 1)
|
||||
;
|
||||
dmx->skip_first_data_page = false;
|
||||
return;
|
||||
}
|
||||
|
||||
while (ogg_stream_packetout(&dmx->os, &op) == 1) {
|
||||
eos = op.e_o_s;
|
||||
|
||||
@ -924,32 +944,35 @@ ogm_reader_c::process_page(ogg_page *og) {
|
||||
}
|
||||
#endif
|
||||
|
||||
hdrlen = (*op.packet & PACKET_LEN_BITS01) >> 6;
|
||||
hdrlen |= (*op.packet & PACKET_LEN_BITS2) << 1;
|
||||
if ((hdrlen > 0) && (op.bytes >= (hdrlen + 1)))
|
||||
for (i = 0, lenbytes = 0; i < hdrlen; i++) {
|
||||
lenbytes = lenbytes << 8;
|
||||
lenbytes += *((unsigned char *)op.packet + hdrlen - i);
|
||||
duration_len = (*op.packet & PACKET_LEN_BITS01) >> 6;
|
||||
duration_len |= (*op.packet & PACKET_LEN_BITS2) << 1;
|
||||
if ((duration_len > 0) && (op.bytes >= (duration_len + 1)))
|
||||
for (i = 0, duration = 0; i < duration_len; i++) {
|
||||
duration = duration << 8;
|
||||
duration += *((unsigned char *)op.packet + duration_len - i);
|
||||
}
|
||||
|
||||
if (((*op.packet & 3) != PACKET_TYPE_HEADER) &&
|
||||
((*op.packet & 3) != PACKET_TYPE_COMMENT)) {
|
||||
|
||||
if (dmx->stype == OGM_STREAM_TYPE_VIDEO) {
|
||||
memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false);
|
||||
memory_c mem(&op.packet[duration_len + 1], op.bytes - 1 -
|
||||
duration_len, false);
|
||||
PTZR(dmx->ptzr)->process(mem, -1, -1,
|
||||
(*op.packet & PACKET_IS_SYNCPOINT ?
|
||||
VFT_IFRAME : VFT_PFRAMEAUTOMATIC));
|
||||
dmx->units_processed += (hdrlen > 0 ? lenbytes : 1);
|
||||
dmx->units_processed += (duration_len > 0 ? duration : 1);
|
||||
|
||||
} else if (dmx->stype == OGM_STREAM_TYPE_TEXT) {
|
||||
dmx->units_processed++;
|
||||
if (((op.bytes - 1 - hdrlen) > 2) ||
|
||||
((op.packet[hdrlen + 1] != ' ') &&
|
||||
(op.packet[hdrlen + 1] != 0) && !iscr(op.packet[hdrlen + 1]))) {
|
||||
memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false);
|
||||
if (((op.bytes - 1 - duration_len) > 2) ||
|
||||
((op.packet[duration_len + 1] != ' ') &&
|
||||
(op.packet[duration_len + 1] != 0) &&
|
||||
!iscr(op.packet[duration_len + 1]))) {
|
||||
memory_c mem(&op.packet[duration_len + 1], op.bytes - 1 -
|
||||
duration_len, false);
|
||||
PTZR(dmx->ptzr)->process(mem, ogg_page_granulepos(og) * 1000000,
|
||||
(int64_t)lenbytes * 1000000);
|
||||
(int64_t)duration * 1000000);
|
||||
}
|
||||
|
||||
} else if (dmx->stype == OGM_STREAM_TYPE_VORBIS) {
|
||||
@ -957,7 +980,8 @@ ogm_reader_c::process_page(ogg_page *og) {
|
||||
PTZR(dmx->ptzr)->process(mem);
|
||||
|
||||
} else {
|
||||
memory_c mem(&op.packet[hdrlen + 1], op.bytes - 1 - hdrlen, false);
|
||||
memory_c mem(&op.packet[duration_len + 1], op.bytes - 1 -
|
||||
duration_len, false);
|
||||
PTZR(dmx->ptzr)->process(mem);
|
||||
dmx->units_processed += op.bytes - 1;
|
||||
}
|
||||
@ -973,26 +997,33 @@ ogm_reader_c::process_page(ogg_page *og) {
|
||||
debug_leave("ogm_reader_c::process_page");
|
||||
}
|
||||
|
||||
/*
|
||||
* Search and store additional headers for the Vorbis streams.
|
||||
*/
|
||||
void
|
||||
ogm_reader_c::process_header_page(ogg_page *og) {
|
||||
ogm_demuxer_t *dmx;
|
||||
ogg_packet op;
|
||||
|
||||
dmx = find_demuxer(ogg_page_serialno(og));
|
||||
if (dmx == NULL)
|
||||
return;
|
||||
if (dmx->headers_read)
|
||||
return;
|
||||
ogg_stream_pagein(&dmx->os, og);
|
||||
process_header_packets(dmx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search and store additional headers for the Ogg streams.
|
||||
*/
|
||||
void
|
||||
ogm_reader_c::process_header_packets(ogm_demuxer_t *dmx) {
|
||||
ogg_packet op;
|
||||
|
||||
if (dmx->headers_read)
|
||||
return;
|
||||
|
||||
if (dmx->stype == OGM_STREAM_TYPE_FLAC) {
|
||||
#if defined HAVE_FLAC_FORMAT_H
|
||||
ogg_stream_pagein(&dmx->os, og);
|
||||
while ((dmx->packet_data.size() < dmx->flac_header_packets) &&
|
||||
(ogg_stream_packetout(&dmx->os, &op) == 1)) {
|
||||
// while (ogg_stream_packetout(&dmx->os, &op) == 1) {
|
||||
dmx->packet_data.push_back((unsigned char *)
|
||||
safememdup(op.packet, op.bytes));
|
||||
dmx->packet_sizes.push_back(op.bytes);
|
||||
@ -1010,13 +1041,15 @@ ogm_reader_c::process_header_page(ogg_page *og) {
|
||||
return;
|
||||
}
|
||||
|
||||
ogg_stream_pagein(&dmx->os, og);
|
||||
while (ogg_stream_packetout(&dmx->os, &op) == 1) {
|
||||
if ((dmx->stype != OGM_STREAM_TYPE_VORBIS) &&
|
||||
if (((dmx->stype != OGM_STREAM_TYPE_VORBIS) || !dmx->native_mode) &&
|
||||
((op.packet[0] & PACKET_TYPE_BITS) != 1)) {
|
||||
mxverb(2, "ogm_reader: Missing header/comment packets for %d.\n",
|
||||
dmx->serial);
|
||||
mxwarn("ogm_reader: Missing header/comment packets for stream %d in "
|
||||
"'%s'. This file is broken but should be muxed correctly. If "
|
||||
"not please contact the author Moritz Bunkus "
|
||||
"<moritz@bunkus.org>.\n", dmx->serial, ti->fname);
|
||||
dmx->headers_read = true;
|
||||
dmx->skip_first_data_page = true;
|
||||
return;
|
||||
}
|
||||
dmx->packet_data.push_back((unsigned char *)
|
||||
@ -1049,7 +1082,7 @@ ogm_reader_c::read_headers() {
|
||||
|
||||
// Is this the first page of a new stream?
|
||||
if (ogg_page_bos(&og))
|
||||
handle_new_stream(&og);
|
||||
handle_new_stream_and_packets(&og);
|
||||
else { // No, so check if it's still a header page.
|
||||
bos_pages_read = 1;
|
||||
process_header_page(&og);
|
||||
|
@ -73,7 +73,7 @@ struct ogm_demuxer_t {
|
||||
bool headers_set;
|
||||
int sid, stype, serial, eos;
|
||||
int units_processed, vorbis_rate;
|
||||
bool headers_read;
|
||||
bool headers_read, native_mode, skip_first_data_page;
|
||||
char *language, *title;
|
||||
vector<unsigned char *> packet_data, nh_packet_data;
|
||||
vector<int> packet_sizes, nh_packet_sizes;
|
||||
@ -85,7 +85,8 @@ struct ogm_demuxer_t {
|
||||
|
||||
ogm_demuxer_t():
|
||||
ptzr(-1), sid(0), stype(0), serial(0), eos(0), units_processed(0),
|
||||
vorbis_rate(0), headers_read(false), language(NULL), title(NULL) {
|
||||
vorbis_rate(0), headers_read(false), native_mode(true),
|
||||
skip_first_data_page(false), language(NULL), title(NULL) {
|
||||
memset(&os, 0, sizeof(ogg_stream_state));
|
||||
}
|
||||
~ogm_demuxer_t() {
|
||||
@ -124,10 +125,12 @@ private:
|
||||
virtual int read_page(ogg_page *);
|
||||
virtual void add_new_demuxer(ogm_demuxer_t *);
|
||||
virtual void handle_new_stream(ogg_page *);
|
||||
virtual void process_page(ogg_page *);
|
||||
virtual void handle_new_stream_and_packets(ogg_page *);
|
||||
virtual void process_page(ogg_page *);
|
||||
virtual int packet_available();
|
||||
virtual int read_headers();
|
||||
virtual void process_header_page(ogg_page *);
|
||||
virtual void process_header_page(ogg_page *pg);
|
||||
virtual void process_header_packets(ogm_demuxer_t *dmx);
|
||||
virtual void create_packetizers();
|
||||
virtual void create_packetizer(int64_t tid);
|
||||
virtual void free_demuxer(int);
|
||||
|
Loading…
Reference in New Issue
Block a user