|
|
|
@ -64,18 +64,18 @@ static int ogg_save(AVFormatContext *s) |
|
|
|
|
{ |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
struct ogg_state *ost = |
|
|
|
|
av_malloc(sizeof (*ost) + (ogg->nstreams-1) * sizeof (*ogg->streams)); |
|
|
|
|
av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams)); |
|
|
|
|
int i; |
|
|
|
|
ost->pos = avio_tell (s->pb); |
|
|
|
|
ost->curidx = ogg->curidx; |
|
|
|
|
ost->next = ogg->state; |
|
|
|
|
ost->pos = avio_tell(s->pb); |
|
|
|
|
ost->curidx = ogg->curidx; |
|
|
|
|
ost->next = ogg->state; |
|
|
|
|
ost->nstreams = ogg->nstreams; |
|
|
|
|
memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams)); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ogg->nstreams; i++){ |
|
|
|
|
for (i = 0; i < ogg->nstreams; i++) { |
|
|
|
|
struct ogg_stream *os = ogg->streams + i; |
|
|
|
|
os->buf = av_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
memcpy (os->buf, ost->streams[i].buf, os->bufpos); |
|
|
|
|
os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
memcpy(os->buf, ost->streams[i].buf, os->bufpos); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ogg->state = ost; |
|
|
|
@ -95,17 +95,17 @@ static int ogg_restore(AVFormatContext *s, int discard) |
|
|
|
|
|
|
|
|
|
ogg->state = ost->next; |
|
|
|
|
|
|
|
|
|
if (!discard){ |
|
|
|
|
if (!discard) { |
|
|
|
|
struct ogg_stream *old_streams = ogg->streams; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ogg->nstreams; i++) |
|
|
|
|
av_free (ogg->streams[i].buf); |
|
|
|
|
av_free(ogg->streams[i].buf); |
|
|
|
|
|
|
|
|
|
avio_seek (bc, ost->pos, SEEK_SET); |
|
|
|
|
ogg->curidx = ost->curidx; |
|
|
|
|
avio_seek(bc, ost->pos, SEEK_SET); |
|
|
|
|
ogg->curidx = ost->curidx; |
|
|
|
|
ogg->nstreams = ost->nstreams; |
|
|
|
|
ogg->streams = av_realloc (ogg->streams, |
|
|
|
|
ogg->nstreams * sizeof (*ogg->streams)); |
|
|
|
|
ogg->streams = av_realloc(ogg->streams, |
|
|
|
|
ogg->nstreams * sizeof(*ogg->streams)); |
|
|
|
|
|
|
|
|
|
if (ogg->streams) { |
|
|
|
|
memcpy(ogg->streams, ost->streams, |
|
|
|
@ -116,7 +116,7 @@ static int ogg_restore(AVFormatContext *s, int discard) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
av_free (ost); |
|
|
|
|
av_free(ost); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -127,18 +127,18 @@ static int ogg_reset(AVFormatContext *s) |
|
|
|
|
int i; |
|
|
|
|
int64_t start_pos = avio_tell(s->pb); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ogg->nstreams; i++){ |
|
|
|
|
for (i = 0; i < ogg->nstreams; i++) { |
|
|
|
|
struct ogg_stream *os = ogg->streams + i; |
|
|
|
|
os->bufpos = 0; |
|
|
|
|
os->pstart = 0; |
|
|
|
|
os->psize = 0; |
|
|
|
|
os->granule = -1; |
|
|
|
|
os->lastpts = AV_NOPTS_VALUE; |
|
|
|
|
os->lastdts = AV_NOPTS_VALUE; |
|
|
|
|
os->sync_pos = -1; |
|
|
|
|
os->page_pos = 0; |
|
|
|
|
os->nsegs = 0; |
|
|
|
|
os->segp = 0; |
|
|
|
|
os->bufpos = 0; |
|
|
|
|
os->pstart = 0; |
|
|
|
|
os->psize = 0; |
|
|
|
|
os->granule = -1; |
|
|
|
|
os->lastpts = AV_NOPTS_VALUE; |
|
|
|
|
os->lastdts = AV_NOPTS_VALUE; |
|
|
|
|
os->sync_pos = -1; |
|
|
|
|
os->page_pos = 0; |
|
|
|
|
os->nsegs = 0; |
|
|
|
|
os->segp = 0; |
|
|
|
|
os->incomplete = 0; |
|
|
|
|
os->got_data = 0; |
|
|
|
|
if (start_pos <= s->data_offset) { |
|
|
|
@ -157,7 +157,7 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) |
|
|
|
|
|
|
|
|
|
for (i = 0; ogg_codecs[i]; i++) |
|
|
|
|
if (size >= ogg_codecs[i]->magicsize && |
|
|
|
|
!memcmp (buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize)) |
|
|
|
|
!memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize)) |
|
|
|
|
return ogg_codecs[i]; |
|
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
@ -183,7 +183,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) |
|
|
|
|
|
|
|
|
|
os = &ogg->streams[0]; |
|
|
|
|
|
|
|
|
|
buf = os->buf; |
|
|
|
|
buf = os->buf; |
|
|
|
|
bufsize = os->bufsize; |
|
|
|
|
codec = os->codec; |
|
|
|
|
|
|
|
|
@ -193,11 +193,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) |
|
|
|
|
/* Set Ogg stream settings similar to what is done in ogg_new_stream(). We
|
|
|
|
|
* also re-use the ogg_stream allocated buffer */ |
|
|
|
|
memset(os, 0, sizeof(*os)); |
|
|
|
|
os->serial = serial; |
|
|
|
|
os->serial = serial; |
|
|
|
|
os->bufsize = bufsize; |
|
|
|
|
os->buf = buf; |
|
|
|
|
os->header = -1; |
|
|
|
|
os->codec = codec; |
|
|
|
|
os->buf = buf; |
|
|
|
|
os->header = -1; |
|
|
|
|
os->codec = codec; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
@ -205,7 +205,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) |
|
|
|
|
static int ogg_new_stream(AVFormatContext *s, uint32_t serial) |
|
|
|
|
{ |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
int idx = ogg->nstreams; |
|
|
|
|
int idx = ogg->nstreams; |
|
|
|
|
AVStream *st; |
|
|
|
|
struct ogg_stream *os; |
|
|
|
|
size_t size; |
|
|
|
@ -220,13 +220,13 @@ static int ogg_new_stream(AVFormatContext *s, uint32_t serial) |
|
|
|
|
if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 || |
|
|
|
|
!(os = av_realloc(ogg->streams, size))) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
|
ogg->streams = os; |
|
|
|
|
os = ogg->streams + idx; |
|
|
|
|
ogg->streams = os; |
|
|
|
|
os = ogg->streams + idx; |
|
|
|
|
memset(os, 0, sizeof(*os)); |
|
|
|
|
os->serial = serial; |
|
|
|
|
os->bufsize = DECODER_BUFFER_SIZE; |
|
|
|
|
os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
os->header = -1; |
|
|
|
|
os->serial = serial; |
|
|
|
|
os->bufsize = DECODER_BUFFER_SIZE; |
|
|
|
|
os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
os->header = -1; |
|
|
|
|
os->start_granule = OGG_NOGRANULE_VALUE; |
|
|
|
|
if (!os->buf) |
|
|
|
|
return AVERROR(ENOMEM); |
|
|
|
@ -249,11 +249,13 @@ static int ogg_new_buf(struct ogg *ogg, int idx) |
|
|
|
|
struct ogg_stream *os = ogg->streams + idx; |
|
|
|
|
uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
int size = os->bufpos - os->pstart; |
|
|
|
|
if(os->buf){ |
|
|
|
|
|
|
|
|
|
if (os->buf) { |
|
|
|
|
memcpy(nb, os->buf + os->pstart, size); |
|
|
|
|
av_free(os->buf); |
|
|
|
|
} |
|
|
|
|
os->buf = nb; |
|
|
|
|
|
|
|
|
|
os->buf = nb; |
|
|
|
|
os->bufpos = size; |
|
|
|
|
os->pstart = 0; |
|
|
|
|
|
|
|
|
@ -287,7 +289,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
if (ret < 4) |
|
|
|
|
return ret < 0 ? ret : AVERROR_EOF; |
|
|
|
|
|
|
|
|
|
do{ |
|
|
|
|
do { |
|
|
|
|
int c; |
|
|
|
|
|
|
|
|
|
if (sync[sp & 3] == 'O' && |
|
|
|
@ -296,29 +298,31 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
c = avio_r8(bc); |
|
|
|
|
|
|
|
|
|
if (url_feof(bc)) |
|
|
|
|
return AVERROR_EOF; |
|
|
|
|
|
|
|
|
|
sync[sp++ & 3] = c; |
|
|
|
|
}while (i++ < MAX_PAGE_SIZE); |
|
|
|
|
} while (i++ < MAX_PAGE_SIZE); |
|
|
|
|
|
|
|
|
|
if (i >= MAX_PAGE_SIZE){ |
|
|
|
|
av_log (s, AV_LOG_INFO, "ogg, can't find sync word\n"); |
|
|
|
|
if (i >= MAX_PAGE_SIZE) { |
|
|
|
|
av_log(s, AV_LOG_INFO, "cannot find sync word\n"); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (avio_r8(bc) != 0){ /* version */ |
|
|
|
|
if (avio_r8(bc) != 0) { /* version */ |
|
|
|
|
av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n"); |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
flags = avio_r8(bc); |
|
|
|
|
gp = avio_rl64 (bc); |
|
|
|
|
serial = avio_rl32 (bc); |
|
|
|
|
flags = avio_r8(bc); |
|
|
|
|
gp = avio_rl64(bc); |
|
|
|
|
serial = avio_rl32(bc); |
|
|
|
|
avio_skip(bc, 8); /* seq, crc */ |
|
|
|
|
nsegs = avio_r8(bc); |
|
|
|
|
nsegs = avio_r8(bc); |
|
|
|
|
|
|
|
|
|
idx = ogg_find_stream (ogg, serial); |
|
|
|
|
if (idx < 0){ |
|
|
|
|
idx = ogg_find_stream(ogg, serial); |
|
|
|
|
if (idx < 0) { |
|
|
|
|
if (data_packets_seen(ogg)) |
|
|
|
|
idx = ogg_replace_stream(s, serial); |
|
|
|
|
else |
|
|
|
@ -333,7 +337,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
os = ogg->streams + idx; |
|
|
|
|
os->page_pos = avio_tell(bc) - 27; |
|
|
|
|
|
|
|
|
|
if(os->psize > 0) |
|
|
|
|
if (os->psize > 0) |
|
|
|
|
ogg_new_buf(ogg, idx); |
|
|
|
|
|
|
|
|
|
ret = avio_read(bc, os->segments, nsegs); |
|
|
|
@ -341,7 +345,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
return ret < 0 ? ret : AVERROR_EOF; |
|
|
|
|
|
|
|
|
|
os->nsegs = nsegs; |
|
|
|
|
os->segp = 0; |
|
|
|
|
os->segp = 0; |
|
|
|
|
|
|
|
|
|
size = 0; |
|
|
|
|
for (i = 0; i < nsegs; i++) |
|
|
|
@ -350,12 +354,12 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
if (!(flags & OGG_FLAG_BOS)) |
|
|
|
|
os->got_data = 1; |
|
|
|
|
|
|
|
|
|
if (flags & OGG_FLAG_CONT || os->incomplete){ |
|
|
|
|
if (!os->psize){ |
|
|
|
|
if (flags & OGG_FLAG_CONT || os->incomplete) { |
|
|
|
|
if (!os->psize) { |
|
|
|
|
// If this is the very first segment we started
|
|
|
|
|
// playback in the middle of a continuation packet.
|
|
|
|
|
// Discard it since we missed the start of it.
|
|
|
|
|
while (os->segp < os->nsegs){ |
|
|
|
|
while (os->segp < os->nsegs) { |
|
|
|
|
int seg = os->segments[os->segp++]; |
|
|
|
|
os->pstart += seg; |
|
|
|
|
if (seg < 255) |
|
|
|
@ -363,15 +367,15 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
} |
|
|
|
|
os->sync_pos = os->page_pos; |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
os->psize = 0; |
|
|
|
|
} else { |
|
|
|
|
os->psize = 0; |
|
|
|
|
os->sync_pos = os->page_pos; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (os->bufsize - os->bufpos < size){ |
|
|
|
|
uint8_t *nb = av_malloc ((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
memcpy (nb, os->buf, os->bufpos); |
|
|
|
|
av_free (os->buf); |
|
|
|
|
if (os->bufsize - os->bufpos < size) { |
|
|
|
|
uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
memcpy(nb, os->buf, os->bufpos); |
|
|
|
|
av_free(os->buf); |
|
|
|
|
os->buf = nb; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -381,7 +385,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) |
|
|
|
|
|
|
|
|
|
os->bufpos += size; |
|
|
|
|
os->granule = gp; |
|
|
|
|
os->flags = flags; |
|
|
|
|
os->flags = flags; |
|
|
|
|
|
|
|
|
|
memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE); |
|
|
|
|
if (sid) |
|
|
|
@ -404,16 +408,16 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, |
|
|
|
|
int idx, i, ret; |
|
|
|
|
struct ogg_stream *os; |
|
|
|
|
int complete = 0; |
|
|
|
|
int segp = 0, psize = 0; |
|
|
|
|
int segp = 0, psize = 0; |
|
|
|
|
|
|
|
|
|
av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx); |
|
|
|
|
if (sid) |
|
|
|
|
*sid = -1; |
|
|
|
|
|
|
|
|
|
do{ |
|
|
|
|
do { |
|
|
|
|
idx = ogg->curidx; |
|
|
|
|
|
|
|
|
|
while (idx < 0){ |
|
|
|
|
while (idx < 0) { |
|
|
|
|
ret = ogg_read_page(s, &idx); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
@ -424,52 +428,54 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, |
|
|
|
|
av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", |
|
|
|
|
idx, os->pstart, os->psize, os->segp, os->nsegs); |
|
|
|
|
|
|
|
|
|
if (!os->codec){ |
|
|
|
|
if (os->header < 0){ |
|
|
|
|
os->codec = ogg_find_codec (os->buf, os->bufpos); |
|
|
|
|
if (!os->codec){ |
|
|
|
|
if (!os->codec) { |
|
|
|
|
if (os->header < 0) { |
|
|
|
|
os->codec = ogg_find_codec(os->buf, os->bufpos); |
|
|
|
|
if (!os->codec) { |
|
|
|
|
av_log(s, AV_LOG_WARNING, "Codec not found\n"); |
|
|
|
|
os->header = 0; |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
} else { |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
segp = os->segp; |
|
|
|
|
segp = os->segp; |
|
|
|
|
psize = os->psize; |
|
|
|
|
|
|
|
|
|
while (os->segp < os->nsegs){ |
|
|
|
|
while (os->segp < os->nsegs) { |
|
|
|
|
int ss = os->segments[os->segp++]; |
|
|
|
|
os->psize += ss; |
|
|
|
|
if (ss < 255){ |
|
|
|
|
if (ss < 255) { |
|
|
|
|
complete = 1; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!complete && os->segp == os->nsegs){ |
|
|
|
|
ogg->curidx = -1; |
|
|
|
|
if (!complete && os->segp == os->nsegs) { |
|
|
|
|
ogg->curidx = -1; |
|
|
|
|
// Do not set incomplete for empty packets.
|
|
|
|
|
// Together with the code in ogg_read_page
|
|
|
|
|
// that discards all continuation of empty packets
|
|
|
|
|
// we would get an infinite loop.
|
|
|
|
|
os->incomplete = !!os->psize; |
|
|
|
|
} |
|
|
|
|
}while (!complete); |
|
|
|
|
} while (!complete); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (os->granule == -1) |
|
|
|
|
av_log(s, AV_LOG_WARNING, "Page at %"PRId64" is missing granule\n", os->page_pos); |
|
|
|
|
av_log(s, AV_LOG_WARNING, |
|
|
|
|
"Page at %"PRId64" is missing granule\n", |
|
|
|
|
os->page_pos); |
|
|
|
|
|
|
|
|
|
ogg->curidx = idx; |
|
|
|
|
ogg->curidx = idx; |
|
|
|
|
os->incomplete = 0; |
|
|
|
|
|
|
|
|
|
if (os->header) { |
|
|
|
|
os->header = os->codec->header (s, idx); |
|
|
|
|
if (!os->header){ |
|
|
|
|
os->segp = segp; |
|
|
|
|
os->header = os->codec->header(s, idx); |
|
|
|
|
if (!os->header) { |
|
|
|
|
os->segp = segp; |
|
|
|
|
os->psize = psize; |
|
|
|
|
|
|
|
|
|
// We have reached the first non-header packet in this stream.
|
|
|
|
@ -481,6 +487,7 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, |
|
|
|
|
// compute the data_offset.
|
|
|
|
|
if (!s->data_offset) |
|
|
|
|
s->data_offset = os->sync_pos; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ogg->nstreams; i++) { |
|
|
|
|
struct ogg_stream *cur_os = ogg->streams + i; |
|
|
|
|
|
|
|
|
@ -489,16 +496,16 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, |
|
|
|
|
if (cur_os->incomplete) |
|
|
|
|
s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos); |
|
|
|
|
} |
|
|
|
|
}else{ |
|
|
|
|
} else { |
|
|
|
|
os->nb_header++; |
|
|
|
|
os->pstart += os->psize; |
|
|
|
|
os->psize = 0; |
|
|
|
|
os->psize = 0; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
os->pflags = 0; |
|
|
|
|
os->pflags = 0; |
|
|
|
|
os->pduration = 0; |
|
|
|
|
if (os->codec && os->codec->packet) |
|
|
|
|
os->codec->packet (s, idx); |
|
|
|
|
os->codec->packet(s, idx); |
|
|
|
|
if (sid) |
|
|
|
|
*sid = idx; |
|
|
|
|
if (dstart) |
|
|
|
@ -507,8 +514,8 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, |
|
|
|
|
*dsize = os->psize; |
|
|
|
|
if (fpos) |
|
|
|
|
*fpos = os->sync_pos; |
|
|
|
|
os->pstart += os->psize; |
|
|
|
|
os->psize = 0; |
|
|
|
|
os->pstart += os->psize; |
|
|
|
|
os->psize = 0; |
|
|
|
|
if(os->pstart == os->bufpos) |
|
|
|
|
os->bufpos = os->pstart = 0; |
|
|
|
|
os->sync_pos = os->page_pos; |
|
|
|
@ -536,7 +543,7 @@ static int ogg_get_length(AVFormatContext *s) |
|
|
|
|
int64_t size, end; |
|
|
|
|
int streams_left=0; |
|
|
|
|
|
|
|
|
|
if(!s->pb->seekable) |
|
|
|
|
if (!s->pb->seekable) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
// already set
|
|
|
|
@ -544,30 +551,30 @@ static int ogg_get_length(AVFormatContext *s) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
size = avio_size(s->pb); |
|
|
|
|
if(size < 0) |
|
|
|
|
if (size < 0) |
|
|
|
|
return 0; |
|
|
|
|
end = size > MAX_PAGE_SIZE? size - MAX_PAGE_SIZE: 0; |
|
|
|
|
end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0; |
|
|
|
|
|
|
|
|
|
ogg_save (s); |
|
|
|
|
avio_seek (s->pb, end, SEEK_SET); |
|
|
|
|
ogg_save(s); |
|
|
|
|
avio_seek(s->pb, end, SEEK_SET); |
|
|
|
|
|
|
|
|
|
while (!ogg_read_page (s, &i)){ |
|
|
|
|
while (!ogg_read_page(s, &i)) { |
|
|
|
|
if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 && |
|
|
|
|
ogg->streams[i].codec) { |
|
|
|
|
s->streams[i]->duration = |
|
|
|
|
ogg_gptopts (s, i, ogg->streams[i].granule, NULL); |
|
|
|
|
if (s->streams[i]->start_time != AV_NOPTS_VALUE){ |
|
|
|
|
ogg_gptopts(s, i, ogg->streams[i].granule, NULL); |
|
|
|
|
if (s->streams[i]->start_time != AV_NOPTS_VALUE) { |
|
|
|
|
s->streams[i]->duration -= s->streams[i]->start_time; |
|
|
|
|
streams_left-= (ogg->streams[i].got_start==-1); |
|
|
|
|
ogg->streams[i].got_start= 1; |
|
|
|
|
}else if(!ogg->streams[i].got_start){ |
|
|
|
|
} else if(!ogg->streams[i].got_start) { |
|
|
|
|
ogg->streams[i].got_start= -1; |
|
|
|
|
streams_left++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ogg_restore (s, 0); |
|
|
|
|
ogg_restore(s, 0); |
|
|
|
|
|
|
|
|
|
ogg_save (s); |
|
|
|
|
avio_seek (s->pb, s->data_offset, SEEK_SET); |
|
|
|
@ -576,11 +583,11 @@ static int ogg_get_length(AVFormatContext *s) |
|
|
|
|
int64_t pts; |
|
|
|
|
if (i < 0) continue; |
|
|
|
|
pts = ogg_calc_pts(s, i, NULL); |
|
|
|
|
if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){ |
|
|
|
|
if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) { |
|
|
|
|
s->streams[i]->duration -= pts; |
|
|
|
|
ogg->streams[i].got_start= 1; |
|
|
|
|
streams_left--; |
|
|
|
|
}else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start){ |
|
|
|
|
}else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) { |
|
|
|
|
ogg->streams[i].got_start= 1; |
|
|
|
|
streams_left--; |
|
|
|
|
} |
|
|
|
@ -622,22 +629,22 @@ static int ogg_read_header(AVFormatContext *s) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//linear granulepos seek from end
|
|
|
|
|
ogg_get_length (s); |
|
|
|
|
ogg_get_length(s); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts) |
|
|
|
|
{ |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
struct ogg_stream *os = ogg->streams + idx; |
|
|
|
|
int64_t pts = AV_NOPTS_VALUE; |
|
|
|
|
int64_t pts = AV_NOPTS_VALUE; |
|
|
|
|
|
|
|
|
|
if (dts) |
|
|
|
|
*dts = AV_NOPTS_VALUE; |
|
|
|
|
|
|
|
|
|
if (os->lastpts != AV_NOPTS_VALUE) { |
|
|
|
|
pts = os->lastpts; |
|
|
|
|
pts = os->lastpts; |
|
|
|
|
os->lastpts = AV_NOPTS_VALUE; |
|
|
|
|
} |
|
|
|
|
if (os->lastdts != AV_NOPTS_VALUE) { |
|
|
|
@ -680,14 +687,14 @@ static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt) |
|
|
|
|
|
|
|
|
|
//Get an ogg packet
|
|
|
|
|
retry: |
|
|
|
|
do{ |
|
|
|
|
do { |
|
|
|
|
ret = ogg_packet(s, &idx, &pstart, &psize, &fpos); |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
}while (idx < 0 || !s->streams[idx]); |
|
|
|
|
} while (idx < 0 || !s->streams[idx]); |
|
|
|
|
|
|
|
|
|
ogg = s->priv_data; |
|
|
|
|
os = ogg->streams + idx; |
|
|
|
|
os = ogg->streams + idx; |
|
|
|
|
|
|
|
|
|
// pflags might not be set until after this
|
|
|
|
|
pts = ogg_calc_pts(s, idx, &dts); |
|
|
|
@ -702,13 +709,13 @@ retry: |
|
|
|
|
if (ret < 0) |
|
|
|
|
return ret; |
|
|
|
|
pkt->stream_index = idx; |
|
|
|
|
memcpy (pkt->data, os->buf + pstart, psize); |
|
|
|
|
memcpy(pkt->data, os->buf + pstart, psize); |
|
|
|
|
|
|
|
|
|
pkt->pts = pts; |
|
|
|
|
pkt->dts = dts; |
|
|
|
|
pkt->flags = os->pflags; |
|
|
|
|
pkt->pts = pts; |
|
|
|
|
pkt->dts = dts; |
|
|
|
|
pkt->flags = os->pflags; |
|
|
|
|
pkt->duration = os->pduration; |
|
|
|
|
pkt->pos = fpos; |
|
|
|
|
pkt->pos = fpos; |
|
|
|
|
|
|
|
|
|
return psize; |
|
|
|
|
} |
|
|
|
@ -718,11 +725,11 @@ static int ogg_read_close(AVFormatContext *s) |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
for (i = 0; i < ogg->nstreams; i++){ |
|
|
|
|
av_free (ogg->streams[i].buf); |
|
|
|
|
av_free (ogg->streams[i].private); |
|
|
|
|
for (i = 0; i < ogg->nstreams; i++) { |
|
|
|
|
av_free(ogg->streams[i].buf); |
|
|
|
|
av_free(ogg->streams[i].private); |
|
|
|
|
} |
|
|
|
|
av_free (ogg->streams); |
|
|
|
|
av_free(ogg->streams); |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -731,14 +738,15 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, |
|
|
|
|
{ |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
AVIOContext *bc = s->pb; |
|
|
|
|
int64_t pts = AV_NOPTS_VALUE; |
|
|
|
|
int64_t keypos = -1; |
|
|
|
|
int64_t pts = AV_NOPTS_VALUE; |
|
|
|
|
int64_t keypos = -1; |
|
|
|
|
int i; |
|
|
|
|
int pstart, psize; |
|
|
|
|
avio_seek(bc, *pos_arg, SEEK_SET); |
|
|
|
|
ogg_reset(s); |
|
|
|
|
|
|
|
|
|
while (avio_tell(bc) <= pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { |
|
|
|
|
while ( avio_tell(bc) <= pos_limit |
|
|
|
|
&& !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { |
|
|
|
|
if (i == stream_index) { |
|
|
|
|
struct ogg_stream *os = ogg->streams + stream_index; |
|
|
|
|
pts = ogg_calc_pts(s, i, NULL); |
|
|
|
@ -764,7 +772,7 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, |
|
|
|
|
static int ogg_read_seek(AVFormatContext *s, int stream_index, |
|
|
|
|
int64_t timestamp, int flags) |
|
|
|
|
{ |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
struct ogg *ogg = s->priv_data; |
|
|
|
|
struct ogg_stream *os = ogg->streams + stream_index; |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
@ -780,7 +788,7 @@ static int ogg_read_seek(AVFormatContext *s, int stream_index, |
|
|
|
|
os->keyframe_seek = 1; |
|
|
|
|
|
|
|
|
|
ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); |
|
|
|
|
os = ogg->streams + stream_index; |
|
|
|
|
os = ogg->streams + stream_index; |
|
|
|
|
if (ret < 0) |
|
|
|
|
os->keyframe_seek = 0; |
|
|
|
|
return ret; |
|
|
|
|