Unverified Commit e983197c authored by Lynne's avatar Lynne

oggdec: use ffio_ensure_seekback() to seek back on incorrect data

This cleans up the code and simplifies it.
It also speeds up parsing since the old pb position was incorrect.
parent 9ad47762
...@@ -206,59 +206,40 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) ...@@ -206,59 +206,40 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
* situation where a new audio stream spawn (identified with a new serial) and * situation where a new audio stream spawn (identified with a new serial) and
* must replace the previous one (track switch). * must replace the previous one (track switch).
*/ */
static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, int size) static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic)
{ {
struct ogg *ogg = s->priv_data; struct ogg *ogg = s->priv_data;
struct ogg_stream *os; struct ogg_stream *os;
const struct ogg_codec *codec; const struct ogg_codec *codec;
int i = 0; int i = 0;
if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { if (ogg->nstreams != 1) {
uint8_t magic[8];
avio_seek(s->pb, -size, SEEK_CUR);
if (avio_read(s->pb, magic, sizeof(magic)) != sizeof(magic))
return AVERROR_INVALIDDATA;
avio_seek(s->pb, size - sizeof(magic), SEEK_CUR);
codec = ogg_find_codec(magic, sizeof(magic));
if (!codec) {
av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
return AVERROR_INVALIDDATA;
}
for (i = 0; i < ogg->nstreams; i++) {
if (ogg->streams[i].codec == codec)
break;
}
if (i >= ogg->nstreams)
return ogg_new_stream(s, serial);
} else if (ogg->nstreams != 1) {
avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg"); avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
return AVERROR_PATCHWELCOME; return AVERROR_PATCHWELCOME;
} }
os = &ogg->streams[i]; /* Check for codecs */
codec = ogg_find_codec(magic, 8);
os->serial = serial; if (!codec) {
return i; av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
return AVERROR_INVALIDDATA;
}
#if 0 /* If the codec matches, then we assume its a replacement */
buf = os->buf; for (i = 0; i < ogg->nstreams; i++) {
bufsize = os->bufsize; if (ogg->streams[i].codec == codec)
codec = os->codec; break;
}
if (!ogg->state || ogg->state->streams[i].private != os->private) /* Otherwise, create a new stream */
av_freep(&ogg->streams[i].private); if (i >= ogg->nstreams)
return ogg_new_stream(s, serial);
/* Set Ogg stream settings similar to what is done in ogg_new_stream(). We os = &ogg->streams[i];
* also re-use the ogg_stream allocated buffer */ os->serial = serial;
memset(os, 0, sizeof(*os)); os->codec = codec;
os->serial = serial;
os->bufsize = bufsize;
os->buf = buf;
os->header = -1;
os->codec = codec;
return i; return i;
#endif
} }
static int ogg_new_stream(AVFormatContext *s, uint32_t serial) static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
...@@ -325,6 +306,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) ...@@ -325,6 +306,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
uint32_t crc, crc_tmp; uint32_t crc, crc_tmp;
int size = 0, idx; int size = 0, idx;
int64_t version, page_pos; int64_t version, page_pos;
int64_t start_pos;
uint8_t sync[4]; uint8_t sync[4];
uint8_t segments[255]; uint8_t segments[255];
uint8_t *readout_buf; uint8_t *readout_buf;
...@@ -364,6 +346,10 @@ static int ogg_read_page(AVFormatContext *s, int *sid) ...@@ -364,6 +346,10 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
/* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */ /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f); ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
/* To rewind if checksum is bad/check magic on switches - this is the max packet size */
ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
start_pos = avio_tell(bc);
version = avio_r8(bc); version = avio_r8(bc);
flags = avio_r8(bc); flags = avio_r8(bc);
gp = avio_rl64(bc); gp = avio_rl64(bc);
...@@ -414,7 +400,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) ...@@ -414,7 +400,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
av_log(s, AV_LOG_ERROR, "CRC mismatch!\n"); av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
if (idx < 0) if (idx < 0)
av_free(readout_buf); av_free(readout_buf);
avio_seek(bc, -size, SEEK_CUR); avio_seek(bc, start_pos, SEEK_SET);
return 0; return 0;
} }
...@@ -424,14 +410,14 @@ static int ogg_read_page(AVFormatContext *s, int *sid) ...@@ -424,14 +410,14 @@ static int ogg_read_page(AVFormatContext *s, int *sid)
av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n"); av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
if (idx < 0) if (idx < 0)
av_free(readout_buf); av_free(readout_buf);
avio_seek(bc, -size, SEEK_CUR); avio_seek(bc, start_pos, SEEK_SET);
return 0; return 0;
} }
/* CRC is correct so we can be 99% sure there's an actual change here */ /* CRC is correct so we can be 99% sure there's an actual change here */
if (idx < 0) { if (idx < 0) {
if (data_packets_seen(ogg)) if (data_packets_seen(ogg))
idx = ogg_replace_stream(s, serial, size); idx = ogg_replace_stream(s, serial, readout_buf);
else else
idx = ogg_new_stream(s, serial); idx = ogg_new_stream(s, serial);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment