X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Foggdec.c;h=30583c495dc27b271c77c8a94a6e763c1d22db1b;hb=db1ba2213f70ad958ba4ec961042ea5a9e52fc9f;hp=11645c945d6cdef46707bd96366ff3fabb6601da;hpb=465c7de7924db37f21bb47c667466aeddedde05d;p=ffmpeg diff --git a/libavformat/oggdec.c b/libavformat/oggdec.c index 11645c945d6..30583c495dc 100644 --- a/libavformat/oggdec.c +++ b/libavformat/oggdec.c @@ -57,25 +57,24 @@ static const struct ogg_codec * const ogg_codecs[] = { }; static int64_t ogg_calc_pts(AVFormatContext *s, int idx, int64_t *dts); -static int ogg_read_close(AVFormatContext *s); //FIXME We could avoid some structure duplication 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; + 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_mallocz (os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy (os->buf, ost->streams[i].buf, os->bufpos); + os->buf = av_mallocz(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(os->buf, ost->streams[i].buf, os->bufpos); } ogg->state = ost; @@ -95,17 +94,17 @@ static int ogg_restore(AVFormatContext *s, int discard) ogg->state = ost->next; - if (!discard){ + if (!discard) { struct ogg_stream *old_streams = ogg->streams; 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; - ogg->streams = av_realloc (ogg->streams, - ogg->nstreams * sizeof (*ogg->streams)); + ogg->streams = av_realloc(ogg->streams, + ogg->nstreams * sizeof(*ogg->streams)); if (ogg->streams) { memcpy(ogg->streams, ost->streams, @@ -116,7 +115,7 @@ static int ogg_restore(AVFormatContext *s, int discard) } } - av_free (ost); + av_free(ost); return 0; } @@ -127,18 +126,18 @@ static int ogg_reset(AVFormatContext *s) int i; int64_t start_pos = avio_tell(s->pb); - 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; os->got_data = 0; if (start_pos <= s->data_offset) { @@ -157,7 +156,7 @@ static const struct ogg_codec *ogg_find_codec(uint8_t *buf, int size) 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; @@ -174,7 +173,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) struct ogg_stream *os; unsigned bufsize; uint8_t *buf; - struct ogg_codec *codec; + const struct ogg_codec *codec; if (ogg->nstreams != 1) { av_log_missing_feature(s, "Changing stream parameters in multistream ogg", 0); @@ -183,7 +182,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) os = &ogg->streams[0]; - buf = os->buf; + buf = os->buf; bufsize = os->bufsize; codec = os->codec; @@ -193,11 +192,11 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) /* Set Ogg stream settings similar to what is done in ogg_new_stream(). We * also re-use the ogg_stream allocated buffer */ memset(os, 0, sizeof(*os)); - os->serial = serial; + os->serial = serial; os->bufsize = bufsize; - os->buf = buf; - os->header = -1; - os->codec = codec; + os->buf = buf; + os->header = -1; + os->codec = codec; return 0; } @@ -205,7 +204,7 @@ static int ogg_replace_stream(AVFormatContext *s, uint32_t serial) static int ogg_new_stream(AVFormatContext *s, uint32_t serial) { struct ogg *ogg = s->priv_data; - int idx = ogg->nstreams; + int idx = ogg->nstreams; AVStream *st; struct ogg_stream *os; size_t size; @@ -221,12 +220,12 @@ static int ogg_new_stream(AVFormatContext *s, uint32_t serial) !(os = av_realloc(ogg->streams, size))) return AVERROR(ENOMEM); ogg->streams = os; - os = ogg->streams + idx; + os = ogg->streams + idx; memset(os, 0, sizeof(*os)); - os->serial = serial; - os->bufsize = DECODER_BUFFER_SIZE; - os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); - os->header = -1; + os->serial = serial; + os->bufsize = DECODER_BUFFER_SIZE; + os->buf = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); + os->header = -1; os->start_granule = OGG_NOGRANULE_VALUE; if (!os->buf) return AVERROR(ENOMEM); @@ -249,11 +248,13 @@ static int ogg_new_buf(struct ogg *ogg, int idx) struct ogg_stream *os = ogg->streams + idx; uint8_t *nb = av_malloc(os->bufsize + FF_INPUT_BUFFER_PADDING_SIZE); int size = os->bufpos - os->pstart; - if(os->buf){ + + 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; @@ -287,7 +288,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) if (ret < 4) return ret < 0 ? ret : AVERROR_EOF; - do{ + do { int c; if (sync[sp & 3] == 'O' && @@ -296,29 +297,31 @@ static int ogg_read_page(AVFormatContext *s, int *sid) break; c = avio_r8(bc); + if (url_feof(bc)) 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"); + 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 */ + if (avio_r8(bc) != 0) { /* version */ av_log (s, AV_LOG_ERROR, "ogg page, unsupported version\n"); return AVERROR_INVALIDDATA; } - flags = avio_r8(bc); - gp = avio_rl64 (bc); - serial = avio_rl32 (bc); + flags = avio_r8(bc); + gp = avio_rl64(bc); + serial = avio_rl32(bc); avio_skip(bc, 8); /* seq, crc */ - nsegs = avio_r8(bc); + nsegs = avio_r8(bc); - idx = ogg_find_stream (ogg, serial); - if (idx < 0){ + idx = ogg_find_stream(ogg, serial); + if (idx < 0) { if (data_packets_seen(ogg)) idx = ogg_replace_stream(s, serial); else @@ -333,7 +336,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) os = ogg->streams + idx; os->page_pos = avio_tell(bc) - 27; - if(os->psize > 0) + if (os->psize > 0) ogg_new_buf(ogg, idx); ret = avio_read(bc, os->segments, nsegs); @@ -341,7 +344,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) return ret < 0 ? ret : AVERROR_EOF; os->nsegs = nsegs; - os->segp = 0; + os->segp = 0; size = 0; for (i = 0; i < nsegs; i++) @@ -350,12 +353,12 @@ static int ogg_read_page(AVFormatContext *s, int *sid) if (!(flags & OGG_FLAG_BOS)) os->got_data = 1; - if (flags & OGG_FLAG_CONT || os->incomplete){ - if (!os->psize){ + if (flags & OGG_FLAG_CONT || os->incomplete) { + if (!os->psize) { // If this is the very first segment we started // playback in the middle of a continuation packet. // Discard it since we missed the start of it. - while (os->segp < os->nsegs){ + while (os->segp < os->nsegs) { int seg = os->segments[os->segp++]; os->pstart += seg; if (seg < 255) @@ -363,15 +366,17 @@ static int ogg_read_page(AVFormatContext *s, int *sid) } 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) + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy (nb, os->buf, os->bufpos); - av_free (os->buf); + if (os->bufsize - os->bufpos < size) { + uint8_t *nb = av_malloc((os->bufsize *= 2) + FF_INPUT_BUFFER_PADDING_SIZE); + if (!nb) + return AVERROR(ENOMEM); + memcpy(nb, os->buf, os->bufpos); + av_free(os->buf); os->buf = nb; } @@ -381,7 +386,7 @@ static int ogg_read_page(AVFormatContext *s, int *sid) os->bufpos += size; os->granule = gp; - os->flags = flags; + os->flags = flags; memset(os->buf + os->bufpos, 0, FF_INPUT_BUFFER_PADDING_SIZE); if (sid) @@ -404,16 +409,16 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, int idx, i, ret; struct ogg_stream *os; int complete = 0; - int segp = 0, psize = 0; + int segp = 0, psize = 0; av_dlog(s, "ogg_packet: curidx=%i\n", ogg->curidx); if (sid) *sid = -1; - do{ + do { idx = ogg->curidx; - while (idx < 0){ + while (idx < 0) { ret = ogg_read_page(s, &idx); if (ret < 0) return ret; @@ -424,52 +429,54 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, av_dlog(s, "ogg_packet: idx=%d pstart=%d psize=%d segp=%d nsegs=%d\n", idx, os->pstart, os->psize, os->segp, os->nsegs); - 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; + 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 (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. @@ -481,6 +488,7 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, // compute the data_offset. if (!s->data_offset) s->data_offset = os->sync_pos; + for (i = 0; i < ogg->nstreams; i++) { struct ogg_stream *cur_os = ogg->streams + i; @@ -489,16 +497,16 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, if (cur_os->incomplete) s->data_offset = FFMIN(s->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 (sid) *sid = idx; if (dstart) @@ -507,8 +515,8 @@ static int ogg_packet(AVFormatContext *s, int *sid, int *dstart, int *dsize, *dsize = os->psize; if (fpos) *fpos = os->sync_pos; - os->pstart += os->psize; - os->psize = 0; + os->pstart += os->psize; + os->psize = 0; if(os->pstart == os->bufpos) os->bufpos = os->pstart = 0; os->sync_pos = os->page_pos; @@ -536,7 +544,7 @@ static int ogg_get_length(AVFormatContext *s) int64_t size, end; int streams_left=0; - if(!s->pb->seekable) + if (!s->pb->seekable) return 0; // already set @@ -544,30 +552,30 @@ static int 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); + ogg_save(s); + 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); - if (s->streams[i]->start_time != AV_NOPTS_VALUE){ + 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; streams_left-= (ogg->streams[i].got_start==-1); ogg->streams[i].got_start= 1; - }else if(!ogg->streams[i].got_start){ + } else if(!ogg->streams[i].got_start) { ogg->streams[i].got_start= -1; streams_left++; } } } - ogg_restore (s, 0); + ogg_restore(s, 0); ogg_save (s); avio_seek (s->pb, s->data_offset, SEEK_SET); @@ -576,11 +584,11 @@ static int ogg_get_length(AVFormatContext *s) int64_t pts; if (i < 0) continue; pts = ogg_calc_pts(s, i, NULL); - if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start){ + if (pts != AV_NOPTS_VALUE && s->streams[i]->start_time == AV_NOPTS_VALUE && !ogg->streams[i].got_start) { s->streams[i]->duration -= pts; ogg->streams[i].got_start= 1; streams_left--; - }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start){ + }else if(s->streams[i]->start_time != AV_NOPTS_VALUE && !ogg->streams[i].got_start) { ogg->streams[i].got_start= 1; streams_left--; } @@ -590,6 +598,23 @@ static int ogg_get_length(AVFormatContext *s) return 0; } +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; @@ -622,22 +647,22 @@ static int ogg_read_header(AVFormatContext *s) } //linear granulepos seek from end - ogg_get_length (s); + ogg_get_length(s); return 0; } 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) { @@ -680,14 +705,14 @@ static int ogg_read_packet(AVFormatContext *s, AVPacket *pkt) //Get an ogg packet retry: - do{ + do { ret = ogg_packet(s, &idx, &pstart, &psize, &fpos); if (ret < 0) return ret; - }while (idx < 0 || !s->streams[idx]); + } 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); @@ -702,43 +727,31 @@ retry: 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) -{ - 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; AVIOContext *bc = s->pb; - int64_t pts = AV_NOPTS_VALUE; - int64_t keypos = -1; + int64_t pts = AV_NOPTS_VALUE; + int64_t keypos = -1; int i; int pstart, psize; avio_seek(bc, *pos_arg, SEEK_SET); ogg_reset(s); - while (avio_tell(bc) <= pos_limit && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { + while ( avio_tell(bc) <= pos_limit + && !ogg_packet(s, &i, &pstart, &psize, pos_arg)) { if (i == stream_index) { struct ogg_stream *os = ogg->streams + stream_index; pts = ogg_calc_pts(s, i, NULL); @@ -764,7 +777,7 @@ static int64_t ogg_read_timestamp(AVFormatContext *s, int stream_index, 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; @@ -780,7 +793,7 @@ static int ogg_read_seek(AVFormatContext *s, int stream_index, os->keyframe_seek = 1; ret = ff_seek_frame_binary(s, stream_index, timestamp, flags); - os = ogg->streams + stream_index; + os = ogg->streams + stream_index; if (ret < 0) os->keyframe_seek = 0; return ret;