History

avformat/oggenc: Avoid allocating and copying when writing page data

When the Ogg muxer writes a page, it has to do three things: It needs to write a page header, then it has to actually copy the page data and then it has to calculate and write a CRC checksum of both header as well as data at a certain position in the page header. To do this, the muxer used a dynamic buffer for both writing as well as calculating the checksum via an AVIOContext's feature to automatically calculate checksums on the data it writes. This entails an allocation of an AVIOContext, of the opaque specific to dynamic buffers and of the buffer itself (which may be reallocated multiple times) as well as memcopying the data (first into the AVIOContext's small write buffer, then into the dynamic buffer's big buffer). This commit changes this: The page header is no longer written into a dynamic buffer any more; instead the (small) page header is written into a small buffer on the stack. The CRC is then calculated directly via av_crc() on both the page header as well as the page data. Then both the page header and the page data are written. Finally, ogg_write_page() can now no longer fail, so it has been modified to return nothing; this also fixed a bug in the only caller of this function: It didn't check the return value.

Andreas Rheinhardt committed 6 years ago

Commit d0bd00c1 parent de7b6901 file · +22 −40Browse files

Unified · Split

libavformat/oggenc.c+22−40
@@ -99,50 +99,32 @@ static const AVClass flavor ## _muxer_class = {\ · 98 unmodified lines
99 .version = LIBAVUTIL_VERSION_INT,\99 .version = LIBAVUTIL_VERSION_INT,\
100};100};
101 101
102static void ogg_update_checksum(AVFormatContext *s, AVIOContext *pb, int64_t crc_offset)102static void ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
103{
104 int64_t pos = avio_tell(pb);
105 uint32_t checksum = ffio_get_checksum(pb);
106 avio_seek(pb, crc_offset, SEEK_SET);
107 avio_wb32(pb, checksum);
108 avio_seek(pb, pos, SEEK_SET);
109}
110
111static int ogg_write_page(AVFormatContext *s, OGGPage *page, int extra_flags)
112{103{
113 OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data;104 OGGStreamContext *oggstream = s->streams[page->stream_index]->priv_data;
114 AVIOContext *pb;105 uint8_t buf[4 + 1 + 1 + 8 + 4 + 4 + 4 + 1 + 255], *ptr = buf, *crc_pos;
115 int64_t crc_offset;106 const AVCRC *crc_table = av_crc_get_table(AV_CRC_32_IEEE);
116 int ret, size;107 uint32_t crc;
117 uint8_t *buf;108
118 109 bytestream_put_le32(&ptr, MKTAG('O', 'g', 'g', 'S'));
119 ret = avio_open_dyn_buf(&pb);110 bytestream_put_byte(&ptr, 0);
120 if (ret < 0)111 bytestream_put_byte(&ptr, page->flags | extra_flags);
121 return ret;112 bytestream_put_le64(&ptr, page->granule);
122 ffio_init_checksum(pb, ff_crc04C11DB7_update, 0);113 bytestream_put_le32(&ptr, oggstream->serial_num);
123 ffio_wfourcc(pb, "OggS");114 bytestream_put_le32(&ptr, oggstream->page_counter++);
124 avio_w8(pb, 0);115 crc_pos = ptr;
125 avio_w8(pb, page->flags | extra_flags);116 bytestream_put_le32(&ptr, 0);
126 avio_wl64(pb, page->granule);117 bytestream_put_byte(&ptr, page->segments_count);
127 avio_wl32(pb, oggstream->serial_num);118 bytestream_put_buffer(&ptr, page->segments, page->segments_count);
128 avio_wl32(pb, oggstream->page_counter++);119
129 crc_offset = avio_tell(pb);120 crc = av_crc(crc_table, 0, buf, ptr - buf);
130 avio_wl32(pb, 0); // crc121 crc = av_crc(crc_table, crc, page->data, page->size);
131 avio_w8(pb, page->segments_count);122 bytestream_put_be32(&crc_pos, crc);
132 avio_write(pb, page->segments, page->segments_count);123
133 avio_write(pb, page->data, page->size);124 avio_write(s->pb, buf, ptr - buf);
134 125 avio_write(s->pb, page->data, page->size);
135 ogg_update_checksum(s, pb, crc_offset);
136
137 size = avio_close_dyn_buf(pb, &buf);
138 if (size < 0)
139 return size;
140
141 avio_write(s->pb, buf, size);
142 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);126 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT);
143 av_free(buf);
144 oggstream->page_count--;127 oggstream->page_count--;
145 return 0;
146}128}
147 129
148static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule)130static int ogg_key_granule(OGGStreamContext *oggstream, int64_t granule)

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t