On 04/30/2013 08:37 AM, Anton Khirnov wrote:
> ---
>  Changelog                 |    1 +
>  doc/muxers.texi           |   21 +++++++++++++++
>  libavformat/matroskaenc.c |   64 
> ++++++++++++++++++++++++++++++++++++++++++++-
>  libavformat/version.h     |    2 +-
>  4 files changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/Changelog b/Changelog
> index 24f0791..e9e0a9f 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -16,6 +16,7 @@ version 9_beta3:
>  - multi-channel ALAC encoding up to 7.1
>  - TAK demuxer, parser, and decoder
>  - adaptive frame-level multithreading for H.264
> +- an option in matroska muxer to put the index at the beginning of the file
>  
>  
>  version 9_beta2:
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index e368e68..19a5806 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -367,6 +367,27 @@ For example a 3D WebM clip can be created using the 
> following command line:
>  avconv -i sample_left_right_clip.mpg -an -c:v libvpx -metadata 
> STEREO_MODE=left_right -y stereo_clip.webm
>  @end example
>  
> +This muxer supports the following options:
> +
> +@table @option
> +
> +@item reserve_index_space
> +By default, this muxer writes the index for seeking (called cues in matroska
> +terms) at the end of the file, because it cannot know in advance how much 
> space
> +to leave for it at the beginning of the file. However for some use cases -- 
> e.g.
> +streaming where seeking is possible but slow -- it is useful to put the 
> index at
> +the beginning of the file.
> +
> +If this option is set to a non-zero value, the muxer will reserve a given 
> amount
> +of space in the file header and then try to write the cues there when the 
> muxing
> +finishes. If there is not enough space, muxing will fail. A safe size for 
> most
> +use cases should be about 50kB per hour of video.
> +
> +Note that cues are only written if the output is seekable and this option 
> will
> +have no effect if it is not.
> +
> +@end table
> +
>  @section segment
>  
>  Basic stream segmenter.
> diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
> index b0998d4..c521ed3 100644
> --- a/libavformat/matroskaenc.c
> +++ b/libavformat/matroskaenc.c
> @@ -34,6 +34,7 @@
>  #include "libavutil/intreadwrite.h"
>  #include "libavutil/lfg.h"
>  #include "libavutil/mathematics.h"
> +#include "libavutil/opt.h"
>  #include "libavutil/random_seed.h"
>  #include "libavutil/samplefmt.h"
>  
> @@ -79,6 +80,7 @@ typedef struct {
>  #define MODE_WEBM       0x02
>  
>  typedef struct MatroskaMuxContext {
> +    const AVClass  *class;
>      int             mode;
>      AVIOContext   *dyn_bc;
>      ebml_master     segment;
> @@ -95,6 +97,9 @@ typedef struct MatroskaMuxContext {
>      AVPacket        cur_audio_pkt;
>  
>      int have_attachments;
> +
> +    int reserve_cues_space;
> +    int64_t cues_pos;
>  } MatroskaMuxContext;
>  
>  
> @@ -968,6 +973,11 @@ static int mkv_write_header(AVFormatContext *s)
>      if (mkv->cues == NULL)
>          return AVERROR(ENOMEM);
>  
> +    if (pb->seekable && mkv->reserve_cues_space) {
> +        mkv->cues_pos = avio_tell(pb);
> +        put_ebml_void(pb, mkv->reserve_cues_space);
> +    }
> +
>      av_init_packet(&mkv->cur_audio_pkt);
>      mkv->cur_audio_pkt.size = 0;
>  
> @@ -1250,7 +1260,28 @@ static int mkv_write_trailer(AVFormatContext *s)
>  
>      if (pb->seekable) {
>          if (mkv->cues->num_entries) {
> -            cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
> +            if (mkv->reserve_cues_space) {
> +                int64_t cues_end;
> +
> +                currentpos = avio_tell(pb);
> +                avio_seek(pb, mkv->cues_pos, SEEK_SET);
> +
> +                cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
> +                cues_end = avio_tell(pb);
> +                if (cues_end > cuespos + mkv->reserve_cues_space) {
> +                    av_log(s, AV_LOG_ERROR, "Insufficient space reserved for 
> cues: %d "
> +                           "(needed: %"PRId64").\n", mkv->reserve_cues_space,
> +                           cues_end - cuespos);
> +                    return AVERROR(EINVAL);

In that case might be better wipe the index and fallback to the normal
situation.

> +                }
> +
> +                if (cues_end < cuespos + mkv->reserve_cues_space)
> +                    put_ebml_void(pb, mkv->reserve_cues_space - (cues_end - 
> cuespos));
> +
> +                avio_seek(pb, currentpos, SEEK_SET);

You could make a static function out of the block above for additional
clarity.

> +            } else {
> +                cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
> +            }

The rest looks good.

lu

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to