Commit efeb3a53 authored by Andreas Rheinhardt's avatar Andreas Rheinhardt

avformat/matroskaenc: Avoid unnecessary seek

The Matroska muxer has a pair of functions designed to write master
elements whose exact length is not known in advance: start_ebml_master()
and end_ebml_master(). The first one of these would write the EBML ID of
the master element that is about to be started, reserve some bytes for
the length field and record the current position as well as how many
bytes were used for the length field. When writing the master's contents
is finished, end_ebml_master() gets the current position (at the end of
the master element), seeks to the length field using the recorded
position, writes the length field and seeks back to the end of the
master element so that one can continue writing other elements.

But if one wants to modify the content of the master element itself,
then the seek back is superfluous. This is the scenario that presents
itself when writing the trailer: One wants to update several elements
contained in the Segment master element (this is the main/root master
element of a Matroska file) that were already written when writing the
header. The current approach is to seek to the beginning of the file
to update the elements, then seek to the end, call end_ebml_master()
which immediately seeks to the beginning to write the length and seeks
back. The seek to the end (which has only been performed because
end_ebml_master() uses the initial position to determine the length
of the master element) and the seek back are of course superfluous.

This commit avoids these seeks by no longer using start/end_ebml_master()
to write the segment's length field. Instead, it is now written
manually. The new approach is: Seek to the beginning to write the length
field, then update the elements (in the order they appear in the file)
and seek back to the end.

This reduces the ordinary amount of seeks of the Matroska muxer to two
(ordinary excludes scenarios where one has big Chapters or Attachments
or where one writes the Cues at the front).
Signed-off-by: 's avatarAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
parent a54c94d9
...@@ -126,7 +126,6 @@ typedef struct MatroskaMuxContext { ...@@ -126,7 +126,6 @@ typedef struct MatroskaMuxContext {
ebml_stored_master info; ebml_stored_master info;
ebml_stored_master track; ebml_stored_master track;
ebml_stored_master tags; ebml_stored_master tags;
ebml_master segment;
int64_t segment_offset; int64_t segment_offset;
AVIOContext *cluster_bc; AVIOContext *cluster_bc;
int64_t cluster_pos; ///< file offset of the current cluster int64_t cluster_pos; ///< file offset of the current cluster
...@@ -1817,7 +1816,8 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1817,7 +1816,8 @@ static int mkv_write_header(AVFormatContext *s)
put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION, 2); put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION, 2);
end_ebml_master(pb, ebml_header); end_ebml_master(pb, ebml_header);
mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0); put_ebml_id(pb, MATROSKA_ID_SEGMENT);
put_ebml_size_unknown(pb, 8);
mkv->segment_offset = avio_tell(pb); mkv->segment_offset = avio_tell(pb);
// we write a seek head at the beginning to point to all other level // we write a seek head at the beginning to point to all other level
...@@ -2542,6 +2542,10 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -2542,6 +2542,10 @@ static int mkv_write_trailer(AVFormatContext *s)
} }
after_cues: after_cues:
if ((ret64 = avio_seek(pb, mkv->segment_offset - 8, SEEK_SET)) < 0)
return ret64;
put_ebml_length(pb, endpos - mkv->segment_offset, 8);
ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -2599,8 +2603,6 @@ static int mkv_write_trailer(AVFormatContext *s) ...@@ -2599,8 +2603,6 @@ static int mkv_write_trailer(AVFormatContext *s)
avio_seek(pb, endpos, SEEK_SET); avio_seek(pb, endpos, SEEK_SET);
end_ebml_master(pb, mkv->segment);
return ret2; return ret2;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment