oggvorbisdec: redesign special handling of first frames timestamp.

This also will make it possible to use the code for cases other than the start of a stream

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-05-04 22:37:51 +02:00
parent 9f357e2bcd
commit 1f95ad48ff
2 changed files with 15 additions and 9 deletions

View File

@ -226,7 +226,8 @@ int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf,
previous_blocksize = s->blocksize[flag]; previous_blocksize = s->blocksize[flag];
} }
current_blocksize = s->mode_blocksize[mode]; current_blocksize = s->mode_blocksize[mode];
duration = (previous_blocksize + current_blocksize) >> 2; if(previous_blocksize)
duration = (previous_blocksize + current_blocksize) >> 2;
s->previous_blocksize = current_blocksize; s->previous_blocksize = current_blocksize;
} }
@ -236,7 +237,7 @@ int avpriv_vorbis_parse_frame(VorbisParseContext *s, const uint8_t *buf,
void avpriv_vorbis_parse_reset(VorbisParseContext *s) void avpriv_vorbis_parse_reset(VorbisParseContext *s)
{ {
if (s->valid_extradata) if (s->valid_extradata)
s->previous_blocksize = s->mode_blocksize[0]; s->previous_blocksize = 0;
} }
#if CONFIG_VORBIS_PARSER #if CONFIG_VORBIS_PARSER

View File

@ -297,28 +297,33 @@ static int vorbis_packet(AVFormatContext *s, int idx)
the total duration to the page granule to find the encoder delay and the total duration to the page granule to find the encoder delay and
set the first timestamp */ set the first timestamp */
if (!os->lastpts) { if (!os->lastpts) {
int seg; int seg, d;
uint8_t *last_pkt = os->buf + os->pstart; uint8_t *last_pkt = os->buf + os->pstart;
uint8_t *next_pkt = last_pkt; uint8_t *next_pkt = last_pkt;
int first_duration = 0;
avpriv_vorbis_parse_reset(&priv->vp); avpriv_vorbis_parse_reset(&priv->vp);
duration = 0; 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) { if (os->segments[seg] < 255) {
int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1); int d = avpriv_vorbis_parse_frame(&priv->vp, last_pkt, 1);
if (d < 0) { if (d < 0) {
duration = os->granule; duration = os->granule;
break; break;
} }
if (!duration)
first_duration = d;
duration += d; duration += d;
last_pkt = next_pkt + os->segments[seg]; last_pkt = next_pkt + os->segments[seg];
} }
next_pkt += os->segments[seg]; next_pkt += os->segments[seg];
} }
os->lastpts = os->lastdts = os->granule - duration + first_duration; os->lastpts = os->lastdts = os->granule - duration;
s->streams[idx]->start_time = os->lastpts; s->streams[idx]->start_time = os->lastpts;
if (s->streams[idx]->duration) if (s->streams[idx]->duration)
s->streams[idx]->duration -= s->streams[idx]->start_time; s->streams[idx]->duration -= s->streams[idx]->start_time;
@ -329,7 +334,7 @@ static int vorbis_packet(AVFormatContext *s, int idx)
/* parse packet duration */ /* parse packet duration */
if (os->psize > 0) { if (os->psize > 0) {
duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1); duration = avpriv_vorbis_parse_frame(&priv->vp, os->buf + os->pstart, 1);
if (duration <= 0) { if (duration < 0) {
os->pflags |= AV_PKT_FLAG_CORRUPT; os->pflags |= AV_PKT_FLAG_CORRUPT;
return 0; return 0;
} }