summaryrefslogtreecommitdiff
path: root/libavformat/oggparsevorbis.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavformat/oggparsevorbis.c')
-rw-r--r--libavformat/oggparsevorbis.c34
1 files changed, 21 insertions, 13 deletions
diff --git a/libavformat/oggparsevorbis.c b/libavformat/oggparsevorbis.c
index 396a3e3ea7..09f5205fbb 100644
--- a/libavformat/oggparsevorbis.c
+++ b/libavformat/oggparsevorbis.c
@@ -203,12 +203,12 @@ vorbis_header (AVFormatContext * s, int idx)
int pkt_type = os->buf[os->pstart];
if (!(pkt_type & 1))
- return 0;
+ return os->private ? 0 : -1;
if (!os->private) {
os->private = av_mallocz(sizeof(struct oggvorbis_private));
if (!os->private)
- return 0;
+ return -1;
}
if (os->psize < 1 || pkt_type > 5)
@@ -223,6 +223,8 @@ vorbis_header (AVFormatContext * s, int idx)
priv->len[pkt_type >> 1] = os->psize;
priv->packet[pkt_type >> 1] = av_mallocz(os->psize);
+ if (!priv->packet[pkt_type >> 1])
+ return AVERROR(ENOMEM);
memcpy(priv->packet[pkt_type >> 1], os->buf + os->pstart, os->psize);
if (os->buf[os->pstart] == 1) {
const uint8_t *p = os->buf + os->pstart + 7; /* skip "\001vorbis" tag */
@@ -296,33 +298,39 @@ static int vorbis_packet(AVFormatContext *s, int idx)
here we parse the duration of each packet in the first page and compare
the total duration to the page granule to find the encoder delay and
set the first timestamp */
- if (!os->lastpts) {
- int seg;
+ if ((!os->lastpts || os->lastpts == AV_NOPTS_VALUE) && !(os->flags & OGG_FLAG_EOS)) {
+ int seg, d;
uint8_t *last_pkt = os->buf + os->pstart;
uint8_t *next_pkt = last_pkt;
- int first_duration = 0;
avpriv_vorbis_parse_reset(&priv->vp);
duration = 0;
- for (seg = 0; seg < os->nsegs; seg++) {
+ seg = os->segp;
+ d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
+ if (d < 0) {
+ os->pflags |= AV_PKT_FLAG_CORRUPT;
+ return 0;
+ }
+ duration += d;
+ last_pkt = next_pkt = next_pkt + os->psize;
+ for (; seg < os->nsegs; seg++) {
if (os->segments[seg] < 255) {
int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
if (d < 0) {
duration = os->granule;
break;
}
- if (!duration)
- first_duration = d;
duration += d;
last_pkt = next_pkt + os->segments[seg];
}
next_pkt += os->segments[seg];
}
os->lastpts = os->lastdts = os->granule - duration;
- s->streams[idx]->start_time = os->lastpts + first_duration;
- if (s->streams[idx]->duration)
- s->streams[idx]->duration -= s->streams[idx]->start_time;
- s->streams[idx]->cur_dts = AV_NOPTS_VALUE;
+ if(s->streams[idx]->start_time == AV_NOPTS_VALUE) {
+ s->streams[idx]->start_time = FFMAX(os->lastpts, 0);
+ if (s->streams[idx]->duration)
+ s->streams[idx]->duration -= s->streams[idx]->start_time;
+ }
priv->final_pts = AV_NOPTS_VALUE;
avpriv_vorbis_parse_reset(&priv->vp);
}
@@ -330,7 +338,7 @@ static int vorbis_packet(AVFormatContext *s, int idx)
/* parse packet duration */
if (os->psize > 0) {
duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
- if (duration <= 0) {
+ if (duration < 0) {
os->pflags |= AV_PKT_FLAG_CORRUPT;
return 0;
}