X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Foggdec.c;h=5965a9730fa6397303b588e5b8df727d775af72c;hb=2f806622e1270d3ed1d41a53049a19673dafbe70;hp=8d96320b3f4832ef64a78c6fd55ee1b26b2a6720;hpb=dc713546d4ffcd2fbc8e0ecd28fbcf6cd252061a;p=ffmpeg diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 8d96320b3f4..5965a9730fa 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -2,10 +2,9 @@ * Ogg bitstream support * Luca Barbato * Based on tcvp implementation - * */ -/** +/* Copyright (C) 2005 Michael Ahlberg, Måns Rullgård Permission is hereby granted, free of charge, to any person @@ -27,12 +26,13 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -**/ + */ #include #include "oggdec.h" #include "avformat.h" +#include "internal.h" #include "vorbiscomment.h" #define MAX_PAGE_SIZE 65307 @@ -45,6 +45,9 @@ static const struct ogg_codec * const ogg_codecs[] = { &ff_vorbis_codec, &ff_theora_codec, &ff_flac_codec, + &ff_celt_codec, + &ff_opus_codec, + &ff_vp8_codec, &ff_old_dirac_codec, &ff_old_flac_codec, &ff_ogm_video_codec, @@ -55,24 +58,24 @@ static const struct ogg_codec * const ogg_codecs[] = { }; //FIXME We could avoid some structure duplication -static int -ogg_save (AVFormatContext * s) +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; + if (!ost) + return AVERROR(ENOMEM); + 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_malloc (os->bufsize); - memset (os->buf, 0, os->bufsize); - memcpy (os->buf, ost->streams[i].buf, os->bufpos); + os->buf = av_mallocz(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); + memcpy(os->buf, ost->streams[i].buf, os->bufpos); } ogg->state = ost; @@ -80,52 +83,56 @@ ogg_save (AVFormatContext * s) return 0; } -static int -ogg_restore (AVFormatContext * s, int discard) +static int ogg_restore(AVFormatContext *s, int discard) { struct ogg *ogg = s->priv_data; AVIOContext *bc = s->pb; struct ogg_state *ost = ogg->state; - int i; + int i, err; if (!ost) return 0; ogg->state = ost->next; - if (!discard){ + if (!discard) { + 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; - memcpy(ogg->streams, ost->streams, - ost->nstreams * sizeof(*ogg->streams)); + if ((err = av_reallocp_array(&ogg->streams, ogg->nstreams, + sizeof(*ogg->streams))) < 0) { + ogg->nstreams = 0; + return err; + } else + memcpy(ogg->streams, ost->streams, + ost->nstreams * sizeof(*ogg->streams)); } - av_free (ost); + av_free(ost); return 0; } -static int -ogg_reset (struct ogg * ogg) +static int ogg_reset(struct ogg *ogg) { int i; - 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; } @@ -134,83 +141,92 @@ ogg_reset (struct ogg * ogg) return 0; } -static const struct ogg_codec * -ogg_find_codec (uint8_t * buf, int size) +static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) { int i; 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; } -static int -ogg_new_stream (AVFormatContext * s, uint32_t serial) +static int ogg_new_stream(AVFormatContext *s, uint32_t serial, int new_avstream) { - struct ogg *ogg = s->priv_data; - int idx = ogg->nstreams++; + int idx = ogg->nstreams++; AVStream *st; struct ogg_stream *os; - ogg->streams = av_realloc (ogg->streams, - ogg->nstreams * sizeof (*ogg->streams)); - memset (ogg->streams + idx, 0, sizeof (*ogg->streams)); - os = ogg->streams + idx; - os->serial = serial; - os->bufsize = DECODER_BUFFER_SIZE; - os->buf = av_malloc(os->bufsize); - os->header = -1; + os = av_realloc(ogg->streams, ogg->nstreams * sizeof(*ogg->streams)); - st = av_new_stream (s, idx); - if (!st) + if (!os) return AVERROR(ENOMEM); - av_set_pts_info(st, 64, 1, 1000000); + ogg->streams = os; + + memset(ogg->streams + idx, 0, sizeof(*ogg->streams)); + + os = ogg->streams + idx; + os->serial = serial; + os->bufsize = DECODER_BUFFER_SIZE; + os->buf = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); + os->header = -1; + os->start_granule = OGG_NOGRANULE_VALUE; + + if (new_avstream) { + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->id = idx; + avpriv_set_pts_info(st, 64, 1, 1000000); + } return idx; } -static int -ogg_new_buf(struct ogg *ogg, int idx) +static int ogg_new_buf(struct ogg *ogg, int idx) { struct ogg_stream *os = ogg->streams + idx; - uint8_t *nb = av_malloc(os->bufsize); + uint8_t *nb = av_malloc(os->bufsize + AV_INPUT_BUFFER_PADDING_SIZE); int size = os->bufpos - os->pstart; - if(os->buf){ + + if (!nb) + return AVERROR(ENOMEM); + + 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; return 0; } -static int -ogg_read_page (AVFormatContext * s, int *str) +static int ogg_read_page(AVFormatContext *s, int *str) { AVIOContext *bc = s->pb; struct ogg *ogg = s->priv_data; struct ogg_stream *os; - int i = 0; + int ret, i = 0; int flags, nsegs; uint64_t gp; uint32_t serial; - uint32_t seq; - uint32_t crc; int size, idx; uint8_t sync[4]; int sp = 0; - if (avio_read (bc, sync, 4) < 4) - return -1; + ret = avio_read(bc, sync, 4); + if (ret < 4) + return ret < 0 ? ret : AVERROR_EOF; - do{ + do { int c; if (sync[sp & 3] == 'O' && @@ -219,62 +235,73 @@ ogg_read_page (AVFormatContext * s, int *str) break; c = avio_r8(bc); + if (bc->eof_reached) - return -1; + 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"); - return -1; + 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 */ - return -1; + return AVERROR_INVALIDDATA; - flags = avio_r8(bc); - gp = avio_rl64 (bc); - serial = avio_rl32 (bc); - seq = avio_rl32 (bc); - crc = avio_rl32 (bc); - nsegs = avio_r8(bc); + flags = avio_r8(bc); + gp = avio_rl64(bc); + serial = avio_rl32(bc); + avio_skip(bc, 8); /* seq, crc */ + nsegs = avio_r8(bc); - idx = ogg_find_stream (ogg, serial); - if (idx < 0){ + idx = ogg_find_stream(ogg, serial); + if (idx < 0) { if (ogg->headers) { int n; for (n = 0; n < ogg->nstreams; n++) { av_freep(&ogg->streams[n].buf); - av_freep(&ogg->streams[n].private); + if (!ogg->state || + ogg->state->streams[n].private != ogg->streams[n].private) + av_freep(&ogg->streams[n].private); } + ogg->curidx = -1; ogg->nstreams = 0; + + idx = ogg_new_stream(s, serial, 0); + } else { + idx = ogg_new_stream(s, serial, 1); } - idx = ogg_new_stream (s, serial); if (idx < 0) - return -1; + return idx; } os = ogg->streams + idx; os->page_pos = avio_tell(bc) - 27; - if(os->psize > 0) - ogg_new_buf(ogg, idx); + if (os->psize > 0) { + ret = ogg_new_buf(ogg, idx); + if (ret < 0) + return ret; + } - if (avio_read (bc, os->segments, nsegs) < nsegs) - return -1; + ret = avio_read(bc, os->segments, nsegs); + if (ret < nsegs) + return ret < 0 ? ret : AVERROR_EOF; os->nsegs = nsegs; - os->segp = 0; + os->segp = 0; size = 0; for (i = 0; i < nsegs; i++) size += os->segments[i]; - if (flags & OGG_FLAG_CONT || os->incomplete){ - if (!os->psize){ - while (os->segp < os->nsegs){ + if (flags & OGG_FLAG_CONT || os->incomplete) { + if (!os->psize) { + while (os->segp < os->nsegs) { int seg = os->segments[os->segp++]; os->pstart += seg; if (seg < 255) @@ -282,137 +309,140 @@ ogg_read_page (AVFormatContext * s, int *str) } 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); - memcpy (nb, os->buf, os->bufpos); - av_free (os->buf); + if (os->bufsize - os->bufpos < size) { + uint8_t *nb = av_malloc((os->bufsize *= 2) + AV_INPUT_BUFFER_PADDING_SIZE); + if (!nb) + return AVERROR(ENOMEM); + memcpy(nb, os->buf, os->bufpos); + av_free(os->buf); os->buf = nb; } - if (avio_read (bc, os->buf + os->bufpos, size) < size) - return -1; + ret = avio_read(bc, os->buf + os->bufpos, size); + if (ret < size) + return ret < 0 ? ret : AVERROR_EOF; os->bufpos += size; os->granule = gp; - os->flags = flags; + os->flags = flags; + memset(os->buf + os->bufpos, 0, AV_INPUT_BUFFER_PADDING_SIZE); if (str) *str = idx; return 0; } -static int -ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpos) +static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, + int64_t *fpos) { struct ogg *ogg = s->priv_data; - int idx, i; + int idx, i, ret; struct ogg_stream *os; int complete = 0; - int segp = 0, psize = 0; + int segp = 0, psize = 0; -#if 0 - av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx); -#endif + av_log(s, AV_LOG_TRACE, "ogg_packet: curidx=%i\n", ogg->curidx); - do{ + do { idx = ogg->curidx; - while (idx < 0){ - if (ogg_read_page (s, &idx) < 0) - return -1; + while (idx < 0) { + ret = ogg_read_page(s, &idx); + if (ret < 0) + return ret; } os = ogg->streams + idx; -#if 0 - av_log (s, AV_LOG_DEBUG, - "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", + av_log(s, AV_LOG_TRACE, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", idx, os->pstart, os->psize, os->segp, os->nsegs); -#endif - 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; - os->incomplete = 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 0 - av_log (s, AV_LOG_DEBUG, - "ogg_packet: idx %i, frame size %i, start %i\n", + av_log(s, AV_LOG_TRACE, "ogg_packet: idx %i, frame size %i, start %i\n", idx, os->psize, os->pstart); -#endif 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. // Unfortunately more header packets may still follow for others, - // so we reset this later unless we are done with the headers - // for all streams. + // but if we continue with header parsing we may lose data packets. ogg->headers = 1; // Update the header state for all streams and // compute the data_offset. - if (!s->data_offset) - s->data_offset = os->sync_pos; + if (!s->internal->data_offset) + s->internal->data_offset = os->sync_pos; + for (i = 0; i < ogg->nstreams; i++) { struct ogg_stream *cur_os = ogg->streams + i; - if (cur_os->header > 0) - ogg->headers = 0; // if we have a partial non-header packet, its start is // obviously at or after the data start if (cur_os->incomplete) - s->data_offset = FFMIN(s->data_offset, cur_os->sync_pos); + s->internal->data_offset = FFMIN(s->internal->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 (str) *str = idx; if (dstart) @@ -421,8 +451,8 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpo *dsize = os->psize; if (fpos) *fpos = os->sync_pos; - os->pstart += os->psize; - os->psize = 0; + os->pstart += os->psize; + os->psize = 0; os->sync_pos = os->page_pos; } @@ -441,31 +471,45 @@ ogg_packet (AVFormatContext * s, int *str, int *dstart, int *dsize, int64_t *fpo return 0; } -static int -ogg_get_headers (AVFormatContext * s) +static int ogg_get_headers(AVFormatContext *s) { struct ogg *ogg = s->priv_data; + int ret, i; - do{ - if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0) - return -1; - }while (!ogg->headers); + do { + ret = ogg_packet(s, NULL, NULL, NULL, NULL); + if (ret < 0) + return ret; + } while (!ogg->headers); -#if 0 - av_log (s, AV_LOG_DEBUG, "found headers\n"); -#endif + for (i = 0; i < ogg->nstreams; i++) { + struct ogg_stream *os = ogg->streams + i; + + if (os->codec && os->codec->nb_header && + os->nb_header < os->codec->nb_header) { + av_log(s, AV_LOG_ERROR, + "Headers mismatch for stream %d: " + "expected %d received %d.\n", + i, os->codec->nb_header, os->nb_header); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + if (os->start_granule != OGG_NOGRANULE_VALUE) + os->lastpts = s->streams[i]->start_time = + ogg_gptopts(s, i, os->start_granule, NULL); + } + av_log(s, AV_LOG_TRACE, "found headers\n"); return 0; } -static int -ogg_get_length (AVFormatContext * s) +static int ogg_get_length(AVFormatContext *s) { struct ogg *ogg = s->priv_data; - int i; + int i, ret; int64_t size, end; - if(!s->pb->seekable) + if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL)) return 0; // already set @@ -473,38 +517,57 @@ 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); + ret = ogg_save(s); + if (ret < 0) + return ret; + 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); + 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; } } - ogg_restore (s, 0); + ogg_restore(s, 0); return 0; } - -static int -ogg_read_header (AVFormatContext * s, AVFormatParameters * ap) +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); + if (ogg->streams[i].codec && + ogg->streams[i].codec->cleanup) { + ogg->streams[i].codec->cleanup(s, i); + } + av_free(ogg->streams[i].private); + } + av_free(ogg->streams); + return 0; +} + +static int ogg_read_header(AVFormatContext *s) +{ + struct ogg *ogg = s->priv_data; + int ret, i; ogg->curidx = -1; //linear headers seek from start - if (ogg_get_headers (s) < 0){ - return -1; + ret = ogg_get_headers(s); + if (ret < 0) { + ogg_read_close(s); + return ret; } for (i = 0; i < ogg->nstreams; i++) @@ -512,7 +575,11 @@ ogg_read_header (AVFormatContext * s, AVFormatParameters * ap) ogg->streams[i].codec = NULL; //linear granulepos seek from end - ogg_get_length (s); + ret = ogg_get_length(s); + if (ret < 0) { + ogg_read_close(s); + return ret; + } //fill the extradata in the per codec callbacks return 0; @@ -520,15 +587,15 @@ ogg_read_header (AVFormatContext * s, AVFormatParameters * ap) 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) { @@ -548,24 +615,24 @@ static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts) return pts; } -static int -ogg_read_packet (AVFormatContext * s, AVPacket * pkt) +static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt) { struct ogg *ogg; struct ogg_stream *os; - int idx = -1; + int idx = -1, ret; int pstart, psize; int64_t fpos, pts, dts; //Get an ogg packet retry: - do{ - if (ogg_packet (s, &idx, &pstart, &psize, &fpos) < 0) - return AVERROR(EIO); - }while (idx < 0 || !s->streams[idx]); + do { + ret = ogg_packet(s, &idx, &pstart, &psize, &fpos); + if (ret < 0) + return ret; + } 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); @@ -575,50 +642,35 @@ retry: os->keyframe_seek = 0; //Alloc a pkt - if (av_new_packet (pkt, psize) < 0) - return AVERROR(EIO); + ret = av_new_packet(pkt, psize); + 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; } - -static int -ogg_read_close (AVFormatContext * s) +static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, + int64_t *pos_arg, int64_t pos_limit) { 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); - } - av_free (ogg->streams); - return 0; -} - - -static int64_t -ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg, - int64_t pos_limit) -{ - struct ogg *ogg = s->priv_data; - struct ogg_stream *os = ogg->streams + stream_index; AVIOContext *bc = s->pb; - int64_t pts = AV_NOPTS_VALUE; - int i; + int64_t pts = AV_NOPTS_VALUE; + int i = -1; avio_seek(bc, *pos_arg, SEEK_SET); ogg_reset(ogg); - while (avio_tell(bc) < pos_limit && !ogg_packet(s, &i, NULL, NULL, pos_arg)) { + while (avio_tell(bc) < pos_limit && + !ogg_packet(s, &i, NULL, NULL, pos_arg)) { if (i == stream_index) { + struct ogg_stream *os = ogg->streams + stream_index; pts = ogg_calc_pts(s, i, NULL); if (os->keyframe_seek && !(os->pflags & AV_PKT_FLAG_KEY)) pts = AV_NOPTS_VALUE; @@ -630,19 +682,21 @@ ogg_read_timestamp (AVFormatContext * s, int stream_index, int64_t * pos_arg, return pts; } -static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +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; // Try seeking to a keyframe first. If this fails (very possible), // av_seek_frame will fall back to ignoring keyframes - if (s->streams[stream_index]->codec->codec_type == AVMEDIA_TYPE_VIDEO + if (s->streams[stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && !(flags & AVSEEK_FLAG_ANY)) os->keyframe_seek = 1; - ret = av_seek_frame_binary(s, stream_index, timestamp, flags); + ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); + os = ogg->streams + stream_index; if (ret < 0) os->keyframe_seek = 0; return ret; @@ -650,24 +704,21 @@ static int ogg_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp static int ogg_probe(AVProbeData *p) { - if (p->buf[0] == 'O' && p->buf[1] == 'g' && - p->buf[2] == 'g' && p->buf[3] == 'S' && - p->buf[4] == 0x0 && p->buf[5] <= 0x7 ) + if (!memcmp("OggS", p->buf, 5) && p->buf[5] <= 0x7) return AVPROBE_SCORE_MAX; - else - return 0; + return 0; } AVInputFormat ff_ogg_demuxer = { - "ogg", - NULL_IF_CONFIG_SMALL("Ogg"), - sizeof (struct ogg), - ogg_probe, - ogg_read_header, - ogg_read_packet, - ogg_read_close, - ogg_read_seek, - ogg_read_timestamp, - .extensions = "ogg", - .flags = AVFMT_GENERIC_INDEX, + .name = "ogg", + .long_name = NULL_IF_CONFIG_SMALL("Ogg"), + .priv_data_size = sizeof(struct ogg), + .read_probe = ogg_probe, + .read_header = ogg_read_header, + .read_packet = ogg_read_packet, + .read_close = ogg_read_close, + .read_seek = ogg_read_seek, + .read_timestamp = ogg_read_timestamp, + .extensions = "ogg", + .flags = AVFMT_GENERIC_INDEX | AVFMT_NOBINSEARCH, };