PageRenderTime 69ms CodeModel.GetById 11ms app.highlight 50ms RepoModel.GetById 2ms app.codeStats 0ms

/libavformat/oggdec.c

http://github.com/FFmpeg/FFmpeg
C | 981 lines | 756 code | 142 blank | 83 comment | 186 complexity | d950acae7e8152175b571cb1794a1fc3 MD5 | raw file
  1/*
  2 * Ogg bitstream support
  3 * Luca Barbato <lu_zero@gentoo.org>
  4 * Based on tcvp implementation
  5 */
  6
  7/*
  8    Copyright (C) 2005  Michael Ahlberg, Måns Rullgård
  9
 10    Permission is hereby granted, free of charge, to any person
 11    obtaining a copy of this software and associated documentation
 12    files (the "Software"), to deal in the Software without
 13    restriction, including without limitation the rights to use, copy,
 14    modify, merge, publish, distribute, sublicense, and/or sell copies
 15    of the Software, and to permit persons to whom the Software is
 16    furnished to do so, subject to the following conditions:
 17
 18    The above copyright notice and this permission notice shall be
 19    included in all copies or substantial portions of the Software.
 20
 21    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 22    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 23    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 24    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 25    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 26    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 27    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 28    DEALINGS IN THE SOFTWARE.
 29 */
 30
 31#include <stdio.h>
 32#include "libavutil/avassert.h"
 33#include "libavutil/intreadwrite.h"
 34#include "avio_internal.h"
 35#include "oggdec.h"
 36#include "avformat.h"
 37#include "internal.h"
 38#include "vorbiscomment.h"
 39
 40#define MAX_PAGE_SIZE 65307
 41#define DECODER_BUFFER_SIZE MAX_PAGE_SIZE
 42
 43static const struct ogg_codec * const ogg_codecs[] = {
 44    &ff_skeleton_codec,
 45    &ff_daala_codec,
 46    &ff_dirac_codec,
 47    &ff_speex_codec,
 48    &ff_vorbis_codec,
 49    &ff_theora_codec,
 50    &ff_flac_codec,
 51    &ff_celt_codec,
 52    &ff_opus_codec,
 53    &ff_vp8_codec,
 54    &ff_old_dirac_codec,
 55    &ff_old_flac_codec,
 56    &ff_ogm_video_codec,
 57    &ff_ogm_audio_codec,
 58    &ff_ogm_text_codec,
 59    &ff_ogm_old_codec,
 60    NULL
 61};
 62
 63static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts);
 64static int ogg_new_stream(AVFormatContext *s, uint32_t serial);
 65static int ogg_restore(AVFormatContext *s);
 66
 67static void free_stream(AVFormatContext *s, int i)
 68{
 69    struct ogg *ogg = s->priv_data;
 70    struct ogg_stream *stream = &ogg->streams[i];
 71
 72    av_freep(&stream->buf);
 73    if (stream->codec &&
 74        stream->codec->cleanup) {
 75        stream->codec->cleanup(s, i);
 76    }
 77
 78    av_freep(&stream->private);
 79    av_freep(&stream->new_metadata);
 80}
 81
 82//FIXME We could avoid some structure duplication
 83static int ogg_save(AVFormatContext *s)
 84{
 85    struct ogg *ogg = s->priv_data;
 86    struct ogg_state *ost =
 87        av_malloc(sizeof(*ost) + (ogg->nstreams - 1) * sizeof(*ogg->streams));
 88    int i;
 89    int ret = 0;
 90
 91    if (!ost)
 92        return AVERROR(ENOMEM);
 93
 94    ost->pos      = avio_tell(s->pb);
 95    ost->curidx   = ogg->curidx;
 96    ost->next     = ogg->state;
 97    ost->nstreams = ogg->nstreams;
 98    memcpy(ost->streams, ogg->streams, ogg->nstreams * sizeof(*ogg->streams));
 99
100    for (i = 0; i < ogg->nstreams; i++) {
101        struct ogg_stream *os = ogg->streams + i;
102        os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
103        if (os->buf)
104            memcpy(os->buf, ost->streams[i].buf, os->bufpos);
105        else
106            ret = AVERROR(ENOMEM);
107        os->new_metadata      = NULL;
108        os->new_metadata_size = 0;
109    }
110
111    ogg->state = ost;
112
113    if (ret < 0)
114        ogg_restore(s);
115
116    return ret;
117}
118
119static int ogg_restore(AVFormatContext *s)
120{
121    struct ogg *ogg = s->priv_data;
122    AVIOContext *bc = s->pb;
123    struct ogg_state *ost = ogg->state;
124    int i, err;
125
126    if (!ost)
127        return 0;
128
129    ogg->state = ost->next;
130
131        for (i = 0; i < ogg->nstreams; i++) {
132            struct ogg_stream *stream = &ogg->streams[i];
133            av_freep(&stream->buf);
134            av_freep(&stream->new_metadata);
135
136            if (i >= ost->nstreams || !ost->streams[i].private) {
137                free_stream(s, i);
138            }
139        }
140
141        avio_seek(bc, ost->pos, SEEK_SET);
142        ogg->page_pos = -1;
143        ogg->curidx   = ost->curidx;
144        ogg->nstreams = ost->nstreams;
145        if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams,
146                                     sizeof(*ogg->streams))) < 0) {
147            ogg->nstreams = 0;
148            return err;
149        } else
150            memcpy(ogg->streams, ost->streams,
151                   ost->nstreams * sizeof(*ogg->streams));
152
153    av_free(ost);
154
155    return 0;
156}
157
158static int ogg_reset(AVFormatContext *s)
159{
160    struct ogg *ogg = s->priv_data;
161    int i;
162    int64_t start_pos = avio_tell(s->pb);
163
164    for (i = 0; i < ogg->nstreams; i++) {
165        struct ogg_stream *os = ogg->streams + i;
166        os->bufpos     = 0;
167        os->pstart     = 0;
168        os->psize      = 0;
169        os->granule    = -1;
170        os->lastpts    = AV_NOPTS_VALUE;
171        os->lastdts    = AV_NOPTS_VALUE;
172        os->sync_pos   = -1;
173        os->page_pos   = 0;
174        os->nsegs      = 0;
175        os->segp       = 0;
176        os->incomplete = 0;
177        os->got_data = 0;
178        if (start_pos <= s->internal->data_offset) {
179            os->lastpts = 0;
180        }
181        os->start_trimming = 0;
182        os->end_trimming = 0;
183        av_freep(&os->new_metadata);
184        os->new_metadata_size = 0;
185    }
186
187    ogg->page_pos = -1;
188    ogg->curidx = -1;
189
190    return 0;
191}
192
193static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size)
194{
195    int i;
196
197    for (i = 0; ogg_codecs[i]; i++)
198        if (size >= ogg_codecs[i]->magicsize &&
199            !memcmp(buf, ogg_codecs[i]->magic, ogg_codecs[i]->magicsize))
200            return ogg_codecs[i];
201
202    return NULL;
203}
204
205/**
206 * Replace the current stream with a new one. This is a typical webradio
207 * situation where a new audio stream spawn (identified with a new serial) and
208 * must replace the previous one (track switch).
209 */
210static int ogg_replace_stream(AVFormatContext *s, uint32_t serial, char *magic,
211                              int probing)
212{
213    struct ogg *ogg = s->priv_data;
214    struct ogg_stream *os;
215    const struct ogg_codec *codec;
216    int i = 0;
217
218    if (ogg->nstreams != 1) {
219        avpriv_report_missing_feature(s, "Changing stream parameters in multistream ogg");
220        return AVERROR_PATCHWELCOME;
221    }
222
223    /* Check for codecs */
224    codec = ogg_find_codec(magic, 8);
225    if (!codec && !probing) {
226        av_log(s, AV_LOG_ERROR, "Cannot identify new stream\n");
227        return AVERROR_INVALIDDATA;
228    }
229
230    /* We only have a single stream anyway, so if there's a new stream with
231     * a different codec just replace it */
232    os = &ogg->streams[0];
233    os->serial  = serial;
234    os->codec   = codec;
235    os->serial  = serial;
236    os->lastpts = 0;
237    os->lastdts = 0;
238    os->start_trimming = 0;
239    os->end_trimming = 0;
240
241    /* Chained files have extradata as a new packet */
242    if (codec == &ff_opus_codec)
243        os->header = -1;
244
245    return i;
246}
247
248static int ogg_new_stream(AVFormatContext *s, uint32_t serial)
249{
250    struct ogg *ogg = s->priv_data;
251    int idx         = ogg->nstreams;
252    AVStream *st;
253    struct ogg_stream *os;
254    size_t size;
255
256    if (ogg->state) {
257        av_log(s, AV_LOG_ERROR, "New streams are not supposed to be added "
258               "in between Ogg context save/restore operations.\n");
259        return AVERROR_BUG;
260    }
261
262    /* Allocate and init a new Ogg Stream */
263    if (av_size_mult(ogg->nstreams + 1, sizeof(*ogg->streams), &size) < 0 ||
264        !(os = av_realloc(ogg->streams, size)))
265        return AVERROR(ENOMEM);
266    ogg->streams = os;
267    os           = ogg->streams + idx;
268    memset(os, 0, sizeof(*os));
269    os->serial        = serial;
270    os->bufsize       = DECODER_BUFFER_SIZE;
271    os->buf           = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
272    os->header        = -1;
273    os->start_granule = OGG_NOGRANULE_VALUE;
274    if (!os->buf)
275        return AVERROR(ENOMEM);
276
277    /* Create the associated AVStream */
278    st = avformat_new_stream(s, NULL);
279    if (!st) {
280        av_freep(&os->buf);
281        return AVERROR(ENOMEM);
282    }
283    st->id = idx;
284    avpriv_set_pts_info(st, 64, 1, 1000000);
285
286    ogg->nstreams++;
287    return idx;
288}
289
290static int data_packets_seen(const struct ogg *ogg)
291{
292    int i;
293
294    for (i = 0; i < ogg->nstreams; i++)
295        if (ogg->streams[i].got_data)
296            return 1;
297    return 0;
298}
299
300static int buf_realloc(struct ogg_stream *os, int size)
301{
302    /* Even if invalid guarantee there's enough memory to read the page */
303    if (os->bufsize - os->bufpos < size) {
304        uint8_t *nb = av_realloc(os->buf, 2*os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE);
305        if (!nb)
306            return AVERROR(ENOMEM);
307        os->buf = nb;
308        os->bufsize *= 2;
309    }
310
311    return 0;
312}
313
314static int ogg_read_page(AVFormatContext *s, int *sid, int probing)
315{
316    AVIOContext *bc = s->pb;
317    struct ogg *ogg = s->priv_data;
318    struct ogg_stream *os;
319    int ret, i = 0;
320    int flags, nsegs;
321    uint64_t gp;
322    uint32_t serial;
323    uint32_t crc, crc_tmp;
324    int size = 0, idx;
325    int64_t version, page_pos;
326    int64_t start_pos;
327    uint8_t sync[4];
328    uint8_t segments[255];
329    uint8_t *readout_buf;
330    int sp = 0;
331
332    ret = avio_read(bc, sync, 4);
333    if (ret < 4)
334        return ret < 0 ? ret : AVERROR_EOF;
335
336    do {
337        int c;
338
339        if (sync[sp & 3] == 'O' &&
340            sync[(sp + 1) & 3] == 'g' &&
341            sync[(sp + 2) & 3] == 'g' && sync[(sp + 3) & 3] == 'S')
342            break;
343
344        if(!i && (bc->seekable & AVIO_SEEKABLE_NORMAL) && ogg->page_pos > 0) {
345            memset(sync, 0, 4);
346            avio_seek(bc, ogg->page_pos+4, SEEK_SET);
347            ogg->page_pos = -1;
348        }
349
350        c = avio_r8(bc);
351
352        if (avio_feof(bc))
353            return AVERROR_EOF;
354
355        sync[sp++ & 3] = c;
356    } while (i++ < MAX_PAGE_SIZE);
357
358    if (i >= MAX_PAGE_SIZE) {
359        av_log(s, AV_LOG_INFO, "cannot find sync word\n");
360        return AVERROR_INVALIDDATA;
361    }
362
363    /* 0x4fa9b05f = av_crc(AV_CRC_32_IEEE, 0x0, "OggS", 4) */
364    ffio_init_checksum(bc, ff_crc04C11DB7_update, 0x4fa9b05f);
365
366    /* To rewind if checksum is bad/check magic on switches - this is the max packet size */
367    ffio_ensure_seekback(bc, MAX_PAGE_SIZE);
368    start_pos = avio_tell(bc);
369
370    version = avio_r8(bc);
371    flags   = avio_r8(bc);
372    gp      = avio_rl64(bc);
373    serial  = avio_rl32(bc);
374    avio_skip(bc, 4); /* seq */
375
376    crc_tmp = ffio_get_checksum(bc);
377    crc     = avio_rb32(bc);
378    crc_tmp = ff_crc04C11DB7_update(crc_tmp, (uint8_t[4]){0}, 4);
379    ffio_init_checksum(bc, ff_crc04C11DB7_update, crc_tmp);
380
381    nsegs    = avio_r8(bc);
382    page_pos = avio_tell(bc) - 27;
383
384    ret = avio_read(bc, segments, nsegs);
385    if (ret < nsegs)
386        return ret < 0 ? ret : AVERROR_EOF;
387
388    for (i = 0; i < nsegs; i++)
389        size += segments[i];
390
391    idx = ogg_find_stream(ogg, serial);
392    if (idx >= 0) {
393        os = ogg->streams + idx;
394
395        ret = buf_realloc(os, size);
396        if (ret < 0)
397            return ret;
398
399        readout_buf = os->buf + os->bufpos;
400    } else {
401        readout_buf = av_malloc(size);
402    }
403
404    ret = avio_read(bc, readout_buf, size);
405    if (ret < size) {
406        if (idx < 0)
407            av_free(readout_buf);
408        return ret < 0 ? ret : AVERROR_EOF;
409    }
410
411    if (crc ^ ffio_get_checksum(bc)) {
412        av_log(s, AV_LOG_ERROR, "CRC mismatch!\n");
413        if (idx < 0)
414            av_free(readout_buf);
415        avio_seek(bc, start_pos, SEEK_SET);
416        return 0;
417    }
418
419    /* Since we're almost sure its a valid packet, checking the version after
420     * the checksum lets the demuxer be more tolerant */
421    if (version) {
422        av_log(s, AV_LOG_ERROR, "Invalid Ogg vers!\n");
423        if (idx < 0)
424            av_free(readout_buf);
425        avio_seek(bc, start_pos, SEEK_SET);
426        return 0;
427    }
428
429    /* CRC is correct so we can be 99% sure there's an actual change here */
430    if (idx < 0) {
431        if (data_packets_seen(ogg))
432            idx = ogg_replace_stream(s, serial, readout_buf, probing);
433        else
434            idx = ogg_new_stream(s, serial);
435
436        if (idx < 0) {
437            av_log(s, AV_LOG_ERROR, "failed to create or replace stream\n");
438            av_free(readout_buf);
439            return idx;
440        }
441
442        os = ogg->streams + idx;
443
444        ret = buf_realloc(os, size);
445        if (ret < 0) {
446            av_free(readout_buf);
447            return ret;
448        }
449
450        memcpy(os->buf + os->bufpos, readout_buf, size);
451        av_free(readout_buf);
452    }
453
454    ogg->page_pos = page_pos;
455    os->page_pos  = page_pos;
456    os->nsegs     = nsegs;
457    os->segp      = 0;
458    os->got_data  = !(flags & OGG_FLAG_BOS);
459    os->bufpos   += size;
460    os->granule   = gp;
461    os->flags     = flags;
462    memcpy(os->segments, segments, nsegs);
463    memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE);
464
465    if (flags & OGG_FLAG_CONT || os->incomplete) {
466        if (!os->psize) {
467            // If this is the very first segment we started
468            // playback in the middle of a continuation packet.
469            // Discard it since we missed the start of it.
470            while (os->segp < os->nsegs) {
471                int seg = os->segments[os->segp++];
472                os->pstart += seg;
473                if (seg < 255)
474                    break;
475            }
476            os->sync_pos = os->page_pos;
477        }
478    } else {
479        os->psize    = 0;
480        os->sync_pos = os->page_pos;
481    }
482
483    /* This function is always called with sid != NULL */
484    *sid = idx;
485
486    return 0;
487}
488
489/**
490 * @brief find the next Ogg packet
491 * @param *sid is set to the stream for the packet or -1 if there is
492 *             no matching stream, in that case assume all other return
493 *             values to be uninitialized.
494 * @return negative value on error or EOF.
495 */
496static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize,
497                      int64_t *fpos)
498{
499    struct ogg *ogg = s->priv_data;
500    int idx, i, ret;
501    struct ogg_stream *os;
502    int complete = 0;
503    int segp     = 0, psize = 0;
504
505    av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx);
506    if (sid)
507        *sid = -1;
508
509    do {
510        idx = ogg->curidx;
511
512        while (idx < 0) {
513            ret = ogg_read_page(s, &idx, 0);
514            if (ret < 0)
515                return ret;
516        }
517
518        os = ogg->streams + idx;
519
520        av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n",
521                idx, os->pstart, os->psize, os->segp, os->nsegs);
522
523        if (!os->codec) {
524            if (os->header < 0) {
525                os->codec = ogg_find_codec(os->buf, os->bufpos);
526                if (!os->codec) {
527                    av_log(s, AV_LOG_WARNING, "Codec not found\n");
528                    os->header = 0;
529                    return 0;
530                }
531            } else {
532                return 0;
533            }
534        }
535
536        segp  = os->segp;
537        psize = os->psize;
538
539        while (os->segp < os->nsegs) {
540            int ss = os->segments[os->segp++];
541            os->psize += ss;
542            if (ss < 255) {
543                complete = 1;
544                break;
545            }
546        }
547
548        if (!complete && os->segp == os->nsegs) {
549            ogg->curidx    = -1;
550            // Do not set incomplete for empty packets.
551            // Together with the code in ogg_read_page
552            // that discards all continuation of empty packets
553            // we would get an infinite loop.
554            os->incomplete = !!os->psize;
555        }
556    } while (!complete);
557
558
559    if (os->granule == -1)
560        av_log(s, AV_LOG_WARNING,
561               "Page at %"PRId64" is missing granule\n",
562               os->page_pos);
563
564    ogg->curidx    = idx;
565    os->incomplete = 0;
566
567    if (os->header) {
568        if ((ret = os->codec->header(s, idx)) < 0) {
569            av_log(s, AV_LOG_ERROR, "Header processing failed: %s\n", av_err2str(ret));
570            return ret;
571        }
572        os->header = ret;
573        if (!os->header) {
574            os->segp  = segp;
575            os->psize = psize;
576
577            // We have reached the first non-header packet in this stream.
578            // Unfortunately more header packets may still follow for others,
579            // but if we continue with header parsing we may lose data packets.
580            ogg->headers = 1;
581
582            // Update the header state for all streams and
583            // compute the data_offset.
584            if (!s->internal->data_offset)
585                s->internal->data_offset = os->sync_pos;
586
587            for (i = 0; i < ogg->nstreams; i++) {
588                struct ogg_stream *cur_os = ogg->streams + i;
589
590                // if we have a partial non-header packet, its start is
591                // obviously at or after the data start
592                if (cur_os->incomplete)
593                    s->internal->data_offset = FFMIN(s->internal->data_offset, cur_os->sync_pos);
594            }
595        } else {
596            os->nb_header++;
597            os->pstart += os->psize;
598            os->psize   = 0;
599        }
600    } else {
601        os->pflags    = 0;
602        os->pduration = 0;
603        if (os->codec && os->codec->packet) {
604            if ((ret = os->codec->packet(s, idx)) < 0) {
605                av_log(s, AV_LOG_ERROR, "Packet processing failed: %s\n", av_err2str(ret));
606                return ret;
607            }
608        }
609        if (sid)
610            *sid = idx;
611        if (dstart)
612            *dstart = os->pstart;
613        if (dsize)
614            *dsize = os->psize;
615        if (fpos)
616            *fpos = os->sync_pos;
617        os->pstart  += os->psize;
618        os->psize    = 0;
619        if(os->pstart == os->bufpos)
620            os->bufpos = os->pstart = 0;
621        os->sync_pos = os->page_pos;
622    }
623
624    // determine whether there are more complete packets in this page
625    // if not, the page's granule will apply to this packet
626    os->page_end = 1;
627    for (i = os->segp; i < os->nsegs; i++)
628        if (os->segments[i] < 255) {
629            os->page_end = 0;
630            break;
631        }
632
633    if (os->segp == os->nsegs)
634        ogg->curidx = -1;
635
636    return 0;
637}
638
639static int ogg_get_length(AVFormatContext *s)
640{
641    struct ogg *ogg = s->priv_data;
642    int i, ret;
643    int64_t size, end;
644    int streams_left=0;
645
646    if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL))
647        return 0;
648
649// already set
650    if (s->duration != AV_NOPTS_VALUE)
651        return 0;
652
653    size = avio_size(s->pb);
654    if (size < 0)
655        return 0;
656    end = size > MAX_PAGE_SIZE ? size - MAX_PAGE_SIZE : 0;
657
658    ret = ogg_save(s);
659    if (ret < 0)
660        return ret;
661    avio_seek(s->pb, end, SEEK_SET);
662    ogg->page_pos = -1;
663
664    while (!ogg_read_page(s, &i, 1)) {
665        if (ogg->streams[i].granule != -1 && ogg->streams[i].granule != 0 &&
666            ogg->streams[i].codec) {
667            s->streams[i]->duration =
668                ogg_gptopts(s, i, ogg->streams[i].granule, NULL);
669            if (s->streams[i]->start_time != AV_NOPTS_VALUE) {
670                s->streams[i]->duration -= s->streams[i]->start_time;
671                streams_left-= (ogg->streams[i].got_start==-1);
672                ogg->streams[i].got_start= 1;
673            } else if(!ogg->streams[i].got_start) {
674                ogg->streams[i].got_start= -1;
675                streams_left++;
676            }
677        }
678    }
679
680    ogg_restore(s);
681
682    ret = ogg_save(s);
683    if (ret < 0)
684        return ret;
685
686    avio_seek (s->pb, s->internal->data_offset, SEEK_SET);
687    ogg_reset(s);
688    while (streams_left > 0 && !ogg_packet(s, &i, NULL, NULL, NULL)) {
689        int64_t pts;
690        if (i < 0) continue;
691        pts = ogg_calc_pts(s, i, NULL);
692        if (s->streams[i]->duration == AV_NOPTS_VALUE)
693            continue;
694        if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
695            s->streams[i]->duration -= pts;
696            ogg->streams[i].got_start= 1;
697            streams_left--;
698        }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) {
699            ogg->streams[i].got_start= 1;
700            streams_left--;
701        }
702    }
703    ogg_restore (s);
704
705    return 0;
706}
707
708static int ogg_read_close(AVFormatContext *s)
709{
710    struct ogg *ogg = s->priv_data;
711    int i;
712
713    for (i = 0; i < ogg->nstreams; i++) {
714        free_stream(s, i);
715    }
716
717    ogg->nstreams = 0;
718
719    av_freep(&ogg->streams);
720    return 0;
721}
722
723static int ogg_read_header(AVFormatContext *s)
724{
725    struct ogg *ogg = s->priv_data;
726    int ret, i;
727
728    ogg->curidx = -1;
729
730    //linear headers seek from start
731    do {
732        ret = ogg_packet(s, NULL, NULL, NULL, NULL);
733        if (ret < 0) {
734            ogg_read_close(s);
735            return ret;
736        }
737    } while (!ogg->headers);
738    av_log(s, AV_LOG_TRACE, "found headers\n");
739
740    for (i = 0; i < ogg->nstreams; i++) {
741        struct ogg_stream *os = ogg->streams + i;
742
743        if (ogg->streams[i].header < 0) {
744            av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i);
745            ogg->streams[i].codec = NULL;
746            av_freep(&ogg->streams[i].private);
747        } else if (os->codec && os->nb_header < os->codec->nb_header) {
748            av_log(s, AV_LOG_WARNING,
749                   "Headers mismatch for stream %d: "
750                   "expected %d received %d.\n",
751                   i, os->codec->nb_header, os->nb_header);
752            if (s->error_recognition & AV_EF_EXPLODE) {
753                ogg_read_close(s);
754                return AVERROR_INVALIDDATA;
755            }
756        }
757        if (os->start_granule != OGG_NOGRANULE_VALUE)
758            os->lastpts = s->streams[i]->start_time =
759                ogg_gptopts(s, i, os->start_granule, NULL);
760    }
761
762    //linear granulepos seek from end
763    ret = ogg_get_length(s);
764    if (ret < 0) {
765        ogg_read_close(s);
766        return ret;
767    }
768
769    return 0;
770}
771
772static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts)
773{
774    struct ogg *ogg       = s->priv_data;
775    struct ogg_stream *os = ogg->streams + idx;
776    int64_t pts           = AV_NOPTS_VALUE;
777
778    if (dts)
779        *dts = AV_NOPTS_VALUE;
780
781    if (os->lastpts != AV_NOPTS_VALUE) {
782        pts         = os->lastpts;
783        os->lastpts = AV_NOPTS_VALUE;
784    }
785    if (os->lastdts != AV_NOPTS_VALUE) {
786        if (dts)
787            *dts = os->lastdts;
788        os->lastdts = AV_NOPTS_VALUE;
789    }
790    if (os->page_end) {
791        if (os->granule != -1LL) {
792            if (os->codec && os->codec->granule_is_start)
793                pts = ogg_gptopts(s, idx, os->granule, dts);
794            else
795                os->lastpts = ogg_gptopts(s, idx, os->granule, &os->lastdts);
796            os->granule = -1LL;
797        }
798    }
799    return pts;
800}
801
802static void ogg_validate_keyframe(AVFormatContext *s, int idx, int pstart, int psize)
803{
804    struct ogg *ogg = s->priv_data;
805    struct ogg_stream *os = ogg->streams + idx;
806    int invalid = 0;
807    if (psize) {
808        switch (s->streams[idx]->codecpar->codec_id) {
809        case AV_CODEC_ID_THEORA:
810            invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 0x40);
811        break;
812        case AV_CODEC_ID_VP8:
813            invalid = !!(os->pflags & AV_PKT_FLAG_KEY) != !(os->buf[pstart] & 1);
814        }
815        if (invalid) {
816            os->pflags ^= AV_PKT_FLAG_KEY;
817            av_log(s, AV_LOG_WARNING, "Broken file, %skeyframe not correctly marked.\n",
818                   (os->pflags & AV_PKT_FLAG_KEY) ? "" : "non-");
819        }
820    }
821}
822
823static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt)
824{
825    struct ogg *ogg;
826    struct ogg_stream *os;
827    int idx, ret;
828    int pstart, psize;
829    int64_t fpos, pts, dts;
830
831    if (s->io_repositioned) {
832        ogg_reset(s);
833        s->io_repositioned = 0;
834    }
835
836    //Get an ogg packet
837retry:
838    do {
839        ret = ogg_packet(s, &idx, &pstart, &psize, &fpos);
840        if (ret < 0)
841            return ret;
842    } while (idx < 0 || !s->streams[idx]);
843
844    ogg = s->priv_data;
845    os  = ogg->streams + idx;
846
847    // pflags might not be set until after this
848    pts = ogg_calc_pts(s, idx, &dts);
849    ogg_validate_keyframe(s, idx, pstart, psize);
850
851    if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY))
852        goto retry;
853    os->keyframe_seek = 0;
854
855    //Alloc a pkt
856    ret = av_new_packet(pkt, psize);
857    if (ret < 0)
858        return ret;
859    pkt->stream_index = idx;
860    memcpy(pkt->data, os->buf + pstart, psize);
861
862    pkt->pts      = pts;
863    pkt->dts      = dts;
864    pkt->flags    = os->pflags;
865    pkt->duration = os->pduration;
866    pkt->pos      = fpos;
867
868    if (os->start_trimming || os->end_trimming) {
869        uint8_t *side_data = av_packet_new_side_data(pkt,
870                                                     AV_PKT_DATA_SKIP_SAMPLES,
871                                                     10);
872        if(!side_data)
873            return AVERROR(ENOMEM);
874         AV_WL32(side_data + 0, os->start_trimming);
875        AV_WL32(side_data + 4, os->end_trimming);
876        os->start_trimming = 0;
877        os->end_trimming = 0;
878    }
879
880    if (os->new_metadata) {
881        uint8_t *side_data = av_packet_new_side_data(pkt,
882                                                     AV_PKT_DATA_METADATA_UPDATE,
883                                                     os->new_metadata_size);
884        if(!side_data)
885            return AVERROR(ENOMEM);
886
887        memcpy(side_data, os->new_metadata, os->new_metadata_size);
888        av_freep(&os->new_metadata);
889        os->new_metadata_size = 0;
890    }
891
892    return psize;
893}
894
895static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index,
896                                  int64_t *pos_arg, int64_t pos_limit)
897{
898    struct ogg *ogg = s->priv_data;
899    AVIOContext *bc = s->pb;
900    int64_t pts     = AV_NOPTS_VALUE;
901    int64_t keypos  = -1;
902    int i;
903    int pstart, psize;
904    avio_seek(bc, *pos_arg, SEEK_SET);
905    ogg_reset(s);
906
907    while (   avio_tell(bc) <= pos_limit
908           && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) {
909        if (i == stream_index) {
910            struct ogg_stream *os = ogg->streams + stream_index;
911            // Do not trust the last timestamps of an ogm video
912            if (    (os->flags & OGG_FLAG_EOS)
913                && !(os->flags & OGG_FLAG_BOS)
914                && os->codec == &ff_ogm_video_codec)
915                continue;
916            pts = ogg_calc_pts(s, i, NULL);
917            ogg_validate_keyframe(s, i, pstart, psize);
918            if (os->pflags & AV_PKT_FLAG_KEY) {
919                keypos = *pos_arg;
920            } else if (os->keyframe_seek) {
921                // if we had a previous keyframe but no pts for it,
922                // return that keyframe with this pts value.
923                if (keypos >= 0)
924                    *pos_arg = keypos;
925                else
926                    pts = AV_NOPTS_VALUE;
927            }
928        }
929        if (pts != AV_NOPTS_VALUE)
930            break;
931    }
932    ogg_reset(s);
933    return pts;
934}
935
936static int ogg_read_seek(AVFormatContext *s, int stream_index,
937                         int64_t timestamp, int flags)
938{
939    struct ogg *ogg       = s->priv_data;
940    struct ogg_stream *os = ogg->streams + stream_index;
941    int ret;
942
943    av_assert0(stream_index < ogg->nstreams);
944    // Ensure everything is reset even when seeking via
945    // the generated index.
946    ogg_reset(s);
947
948    // Try seeking to a keyframe first. If this fails (very possible),
949    // av_seek_frame will fall back to ignoring keyframes
950    if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO
951        && !(flags & AVSEEK_FLAG_ANY))
952        os->keyframe_seek = 1;
953
954    ret = ff_seek_frame_binary(s, stream_index, timestamp, flags);
955    ogg_reset(s);
956    os  = ogg->streams + stream_index;
957    if (ret < 0)
958        os->keyframe_seek = 0;
959    return ret;
960}
961
962static int ogg_probe(const AVProbeData *p)
963{
964    if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7)
965        return AVPROBE_SCORE_MAX;
966    return 0;
967}
968
969AVInputFormat ff_ogg_demuxer = {
970    .name           = "ogg",
971    .long_name      = NULL_IF_CONFIG_SMALL("Ogg"),
972    .priv_data_size = sizeof(struct ogg),
973    .read_probe     = ogg_probe,
974    .read_header    = ogg_read_header,
975    .read_packet    = ogg_read_packet,
976    .read_close     = ogg_read_close,
977    .read_seek      = ogg_read_seek,
978    .read_timestamp = ogg_read_timestamp,
979    .extensions     = "ogg",
980    .flags          = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH,
981};