+ int ret = fixup_vorbis_headers(s, priv, &st->codec->extradata);
+ if (ret < 0) {
+ st->codec->extradata_size = 0;
+ return ret;
+ }
+ st->codec->extradata_size = ret;
+
+ priv->vp = av_vorbis_parse_init(st->codec->extradata, st->codec->extradata_size);
+ if (!priv->vp) {
+ av_freep(&st->codec->extradata);
+ st->codec->extradata_size = 0;
+ return ret;
+ }
+ }
+
+ return 1;
+}
+
+static int vorbis_packet(AVFormatContext *s, int idx)
+{
+ struct ogg *ogg = s->priv_data;
+ struct ogg_stream *os = ogg->streams + idx;
+ struct oggvorbis_private *priv = os->private;
+ int duration;
+
+ if (!priv->vp)
+ return AVERROR_INVALIDDATA;
+
+ /* first packet handling
+ * 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;
+ uint8_t *last_pkt = os->buf + os->pstart;
+ uint8_t *next_pkt = last_pkt;
+ int first_duration = 0;
+
+ av_vorbis_parse_reset(priv->vp);
+ duration = 0;
+ for (seg = 0; seg < os->nsegs; seg++) {
+ if (os->segments[seg] < 255) {
+ int d = av_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;
+ priv->final_pts = AV_NOPTS_VALUE;
+ av_vorbis_parse_reset(priv->vp);