diff options
Diffstat (limited to 'libavformat/oggdec.c')
-rw-r--r-- | libavformat/oggdec.c | 82 |
1 files changed, 54 insertions, 28 deletions
diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 67678059a1..7f6536545b 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -45,6 +45,7 @@ static const struct ogg_codec * const ogg_codecs[] = { &ff_vorbis_codec, &ff_theora_codec, &ff_flac_codec, + &ff_celt_codec, &ff_old_dirac_codec, &ff_old_flac_codec, &ff_ogm_video_codec, @@ -192,7 +193,7 @@ 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; @@ -202,8 +203,9 @@ static int ogg_read_page(AVFormatContext *s, int *str) 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{ int c; @@ -214,18 +216,18 @@ static int ogg_read_page(AVFormatContext *s, int *str) break; c = avio_r8(bc); - if (bc->eof_reached) - return -1; + if (url_feof(bc)) + return AVERROR_EOF; sync[sp++ & 3] = c; }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; + return AVERROR_INVALIDDATA; } if (avio_r8(bc) != 0) /* version */ - return -1; + return AVERROR_INVALIDDATA; flags = avio_r8(bc); gp = avio_rl64 (bc); @@ -250,7 +252,7 @@ static int ogg_read_page(AVFormatContext *s, int *str) idx = ogg_new_stream(s, serial, 1); } if (idx < 0) - return -1; + return idx; } os = ogg->streams + idx; @@ -259,8 +261,9 @@ static int ogg_read_page(AVFormatContext *s, int *str) if(os->psize > 0) ogg_new_buf(ogg, idx); - 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; @@ -291,8 +294,9 @@ static int ogg_read_page(AVFormatContext *s, int *str) 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; @@ -308,31 +312,37 @@ 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; - av_dlog(s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx); +#if 0 + av_log (s, AV_LOG_DEBUG, "ogg_packet: curidx=%i\n", ogg->curidx); +#endif do{ idx = ogg->curidx; while (idx < 0){ - if (ogg_read_page (s, &idx) < 0) - return -1; + ret = ogg_read_page (s, &idx); + if (ret < 0) + return ret; } os = ogg->streams + idx; - av_dlog(s, AV_LOG_DEBUG, +#if 0 + av_log (s, AV_LOG_DEBUG, "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){ + av_log(s, AV_LOG_WARNING, "Codec not found\n"); os->header = 0; return 0; } @@ -359,9 +369,11 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, } }while (!complete); - av_dlog(s, AV_LOG_DEBUG, +#if 0 + av_log (s, AV_LOG_DEBUG, "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); @@ -377,8 +389,7 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, // 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 @@ -387,8 +398,6 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, s->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 @@ -435,13 +444,17 @@ static int ogg_packet(AVFormatContext *s, int *str, int *dstart, int *dsize, static int ogg_get_headers(AVFormatContext *s) { struct ogg *ogg = s->priv_data; + int ret; do{ - if (ogg_packet (s, NULL, NULL, NULL, NULL) < 0) - return -1; + ret = ogg_packet (s, NULL, NULL, NULL, NULL); + if (ret < 0) + return ret; }while (!ogg->headers); - av_dlog(s, AV_LOG_DEBUG, "found headers\n"); +#if 0 + av_log (s, AV_LOG_DEBUG, "found headers\n"); +#endif return 0; } @@ -479,17 +492,30 @@ static int ogg_get_length(AVFormatContext *s) ogg_restore (s, 0); + ogg_save (s); + avio_seek (s->pb, 0, SEEK_SET); + 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); + break; + } + } + ogg_restore (s, 0); + return 0; } static int ogg_read_header(AVFormatContext *s, AVFormatParameters *ap) { struct ogg *ogg = s->priv_data; - int i; + 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){ + return ret; } for (i = 0; i < ogg->nstreams; i++) |