.version = LIBAVUTIL_VERSION_INT,\
};
-static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset)
-{
- int64_t pos = avio_tell(pb);
- uint32_t checksum = ffio_get_checksum(pb);
- avio_seek(pb, crc_offset, SEEK_SET);
- avio_wb32(pb, checksum);
- avio_seek(pb, pos, SEEK_SET);
-}
-
-static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
+static void ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
{
OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data;
- AVIOContext *pb;
- int64_t crc_offset;
- int ret, size;
- uint8_t *buf;
-
- ret = avio_open_dyn_buf(&pb);
- if (ret < 0)
- return ret;
- ffio_init_checksum(pb, ff_crc04C11DB7_update, 0);
- ffio_wfourcc(pb, "OggS");
- avio_w8(pb, 0);
- avio_w8(pb, page->flags | extra_flags);
- avio_wl64(pb, page->granule);
- avio_wl32(pb, oggstream->serial_num);
- avio_wl32(pb, oggstream->page_counter++);
- crc_offset = avio_tell(pb);
- avio_wl32(pb, 0); // crc
- avio_w8(pb, page->segments_count);
- avio_write(pb, page->segments, page->segments_count);
- avio_write(pb, page->data, page->size);
-
- ogg_update_checksum(s, pb, crc_offset);
- avio_flush(pb);
-
- size = avio_close_dyn_buf(pb, &buf);
- if (size < 0)
- return size;
-
- avio_write(s->pb, buf, size);
- avio_flush(s->pb);
- av_free(buf);
+ uint8_t buf[4 + 1 + 1 + 8 + 4 + 4 + 4 + 1 + 255], *ptr = buf, *crc_pos;
+ const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE);
+ uint32_t crc;
+
+ bytestream_put_le32(&ptr, MKTAG('O', 'g', 'g', 'S'));
+ bytestream_put_byte(&ptr, 0);
+ bytestream_put_byte(&ptr, page->flags | extra_flags);
+ bytestream_put_le64(&ptr, page->granule);
+ bytestream_put_le32(&ptr, oggstream->serial_num);
+ bytestream_put_le32(&ptr, oggstream->page_counter++);
+ crc_pos = ptr;
+ bytestream_put_le32(&ptr, 0);
+ bytestream_put_byte(&ptr, page->segments_count);
+ bytestream_put_buffer(&ptr, page->segments, page->segments_count);
+
+ crc = av_crc(crc_table, 0, buf, ptr - buf);
+ crc = av_crc(crc_table, crc, page->data, page->size);
+ bytestream_put_be32(&crc_pos, crc);
+
+ avio_write(s->pb, buf, ptr - buf);
+ avio_write(s->pb, page->data, page->size);
+ avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
oggstream->page_count--;
- return 0;
}
static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule)
AVChapter **chapters, unsigned int nb_chapters)
{
const char *vendor = bitexact ? "ffmpeg" : LIBAVFORMAT_IDENT;
+ AVIOContext pb;
int64_t size;
- uint8_t *p, *p0;
+ uint8_t *p;
ff_metadata_conv(m, ff_vorbiscomment_metadata_conv, NULL);
p = av_mallocz(size);
if (!p)
return NULL;
- p0 = p;
- p += offset;
- ff_vorbiscomment_write(&p, m, vendor, chapters, nb_chapters);
+ ffio_init_context(&pb, p + offset, size - offset, 1, NULL, NULL, NULL, NULL);
+ ff_vorbiscomment_write(&pb, *m, vendor, chapters, nb_chapters);
if (framing_bit)
- bytestream_put_byte(&p, 1);
+ avio_w8(&pb, 1);
*header_len = size;
- return p0;
+ return p;
}
static int ogg_build_flac_headers(AVCodecParameters *par,
&st->metadata);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n");
- av_freep(&st->priv_data);
return err;
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_SPEEX) {
&st->metadata);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n");
- av_freep(&st->priv_data);
return err;
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_OPUS) {
&st->metadata, s->chapters, s->nb_chapters);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n");
- av_freep(&st->priv_data);
return err;
}
} else if (st->codecpar->codec_id == AV_CODEC_ID_VP8) {
s->flags & AVFMT_FLAG_BITEXACT);
if (err) {
av_log(s, AV_LOG_ERROR, "Error writing VP8 headers\n");
- av_freep(&st->priv_data);
return err;
}
} else {
st->codecpar->codec_id == AV_CODEC_ID_VORBIS ? 30 : 42,
(const uint8_t**)oggstream->header, oggstream->header_len) < 0) {
av_log(s, AV_LOG_ERROR, "Extradata corrupted\n");
- av_freep(&st->priv_data);
+ oggstream->header[1] = NULL;
return AVERROR_INVALIDDATA;
}
static void ogg_free(AVFormatContext *s)
{
+ OGGContext *ogg = s->priv_data;
+ OGGPageList *p = ogg->page_list;
int i;
for (i = 0; i < s->nb_streams; i++) {
av_freep(&oggstream->header[0]);
}
av_freep(&oggstream->header[1]);
- av_freep(&st->priv_data);
}
+
+ while (p) {
+ OGGPageList *next = p->next;
+ av_free(p);
+ p = next;
+ }
+ ogg->page_list = NULL;
}
#if CONFIG_OGG_MUXER