X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Foggenc.c;h=af27957c757fcabb4cfb35270f8f898204f35a65;hb=9e13df3776da3a101e895e2840f6f23f5a6f74a0;hp=06021c4f4ba835156a229a794ce8e8e0abd3ec46;hpb=b2f32d60eeaf883bb7d9e1b8cc2fb9a983d08f72;p=ffmpeg diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 06021c4f4ba..af27957c757 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -99,51 +99,32 @@ static const AVClass flavor ## _muxer_class = {\ .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) @@ -295,8 +276,9 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact, 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); @@ -306,15 +288,14 @@ static uint8_t *ogg_write_vorbiscomment(int64_t offset, int bitexact, 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, @@ -547,7 +528,6 @@ static int ogg_init(AVFormatContext *s) &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) { @@ -556,7 +536,6 @@ static int ogg_init(AVFormatContext *s) &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) { @@ -565,7 +544,6 @@ static int ogg_init(AVFormatContext *s) &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) { @@ -573,7 +551,6 @@ static int ogg_init(AVFormatContext *s) 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 { @@ -586,7 +563,7 @@ static int ogg_init(AVFormatContext *s) 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; } @@ -740,6 +717,8 @@ static int ogg_write_trailer(AVFormatContext *s) 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++) { @@ -754,13 +733,19 @@ static void ogg_free(AVFormatContext *s) 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 OGG_CLASS(ogg, Ogg) -AVOutputFormat ff_ogg_muxer = { +const AVOutputFormat ff_ogg_muxer = { .name = "ogg", .long_name = NULL_IF_CONFIG_SMALL("Ogg"), .mime_type = "application/ogg", @@ -791,7 +776,7 @@ AVOutputFormat ff_ogg_muxer = { #if CONFIG_OGA_MUXER OGG_CLASS(oga, Ogg audio) -AVOutputFormat ff_oga_muxer = { +const AVOutputFormat ff_oga_muxer = { .name = "oga", .long_name = NULL_IF_CONFIG_SMALL("Ogg Audio"), .mime_type = "audio/ogg", @@ -810,7 +795,7 @@ AVOutputFormat ff_oga_muxer = { #if CONFIG_OGV_MUXER OGG_CLASS(ogv, Ogg video) -AVOutputFormat ff_ogv_muxer = { +const AVOutputFormat ff_ogv_muxer = { .name = "ogv", .long_name = NULL_IF_CONFIG_SMALL("Ogg Video"), .mime_type = "video/ogg", @@ -832,7 +817,7 @@ AVOutputFormat ff_ogv_muxer = { #if CONFIG_SPX_MUXER OGG_CLASS(spx, Ogg Speex) -AVOutputFormat ff_spx_muxer = { +const AVOutputFormat ff_spx_muxer = { .name = "spx", .long_name = NULL_IF_CONFIG_SMALL("Ogg Speex"), .mime_type = "audio/ogg", @@ -851,7 +836,7 @@ AVOutputFormat ff_spx_muxer = { #if CONFIG_OPUS_MUXER OGG_CLASS(opus, Ogg Opus) -AVOutputFormat ff_opus_muxer = { +const AVOutputFormat ff_opus_muxer = { .name = "opus", .long_name = NULL_IF_CONFIG_SMALL("Ogg Opus"), .mime_type = "audio/ogg",