matroskaenc: add an option to put the index at the start of the file
This commit is contained in:
		
							parent
							
								
									0574bc06d2
								
							
						
					
					
						commit
						e3b225a4fe
					
				@ -16,6 +16,7 @@ version 10:
 | 
			
		||||
- new trim and atrim filters
 | 
			
		||||
- avconv -t and -ss (output-only) options are now sample-accurate when
 | 
			
		||||
  transcoding audio
 | 
			
		||||
- Matroska muxer can now put the index at the beginning of the file.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
version 9:
 | 
			
		||||
 | 
			
		||||
@ -373,6 +373,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 the index 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 the available space does not suffice, 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.
 | 
			
		||||
 | 
			
		||||
@ -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) {
 | 
			
		||||
            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);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                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);
 | 
			
		||||
            } else {
 | 
			
		||||
                cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos);
 | 
			
		||||
            if (ret < 0) return ret;
 | 
			
		||||
@ -1291,7 +1322,22 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance)
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define OFFSET(x) offsetof(MatroskaMuxContext, x)
 | 
			
		||||
#define FLAGS AV_OPT_FLAG_ENCODING_PARAM
 | 
			
		||||
static const AVOption options[] = {
 | 
			
		||||
    { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning "
 | 
			
		||||
        "of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
 | 
			
		||||
    { NULL },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MATROSKA_MUXER
 | 
			
		||||
static const AVClass matroska_class = {
 | 
			
		||||
    .class_name = "matroska muxer",
 | 
			
		||||
    .item_name  = av_default_item_name,
 | 
			
		||||
    .option     = options,
 | 
			
		||||
    .version    = LIBAVUTIL_VERSION_INT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AVOutputFormat ff_matroska_muxer = {
 | 
			
		||||
    .name              = "matroska",
 | 
			
		||||
    .long_name         = NULL_IF_CONFIG_SMALL("Matroska"),
 | 
			
		||||
@ -1312,10 +1358,18 @@ AVOutputFormat ff_matroska_muxer = {
 | 
			
		||||
    },
 | 
			
		||||
    .subtitle_codec    = AV_CODEC_ID_SSA,
 | 
			
		||||
    .query_codec       = mkv_query_codec,
 | 
			
		||||
    .priv_class        = &matroska_class,
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_WEBM_MUXER
 | 
			
		||||
static const AVClass webm_class = {
 | 
			
		||||
    .class_name = "webm muxer",
 | 
			
		||||
    .item_name  = av_default_item_name,
 | 
			
		||||
    .option     = options,
 | 
			
		||||
    .version    = LIBAVUTIL_VERSION_INT,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AVOutputFormat ff_webm_muxer = {
 | 
			
		||||
    .name              = "webm",
 | 
			
		||||
    .long_name         = NULL_IF_CONFIG_SMALL("WebM"),
 | 
			
		||||
@ -1329,10 +1383,17 @@ AVOutputFormat ff_webm_muxer = {
 | 
			
		||||
    .write_trailer     = mkv_write_trailer,
 | 
			
		||||
    .flags             = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS |
 | 
			
		||||
                         AVFMT_TS_NONSTRICT,
 | 
			
		||||
    .priv_class        = &webm_class,
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if CONFIG_MATROSKA_AUDIO_MUXER
 | 
			
		||||
static const AVClass mka_class = {
 | 
			
		||||
    .class_name = "matroska audio muxer",
 | 
			
		||||
    .item_name  = av_default_item_name,
 | 
			
		||||
    .option     = options,
 | 
			
		||||
    .version    = LIBAVUTIL_VERSION_INT,
 | 
			
		||||
};
 | 
			
		||||
AVOutputFormat ff_matroska_audio_muxer = {
 | 
			
		||||
    .name              = "matroska",
 | 
			
		||||
    .long_name         = NULL_IF_CONFIG_SMALL("Matroska"),
 | 
			
		||||
@ -1347,5 +1408,6 @@ AVOutputFormat ff_matroska_audio_muxer = {
 | 
			
		||||
    .write_trailer     = mkv_write_trailer,
 | 
			
		||||
    .flags             = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT,
 | 
			
		||||
    .codec_tag         = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 },
 | 
			
		||||
    .priv_class        = &mka_class,
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -31,7 +31,7 @@
 | 
			
		||||
 | 
			
		||||
#define LIBAVFORMAT_VERSION_MAJOR 55
 | 
			
		||||
#define LIBAVFORMAT_VERSION_MINOR  0
 | 
			
		||||
#define LIBAVFORMAT_VERSION_MICRO  0
 | 
			
		||||
#define LIBAVFORMAT_VERSION_MICRO  1
 | 
			
		||||
 | 
			
		||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
 | 
			
		||||
                                               LIBAVFORMAT_VERSION_MINOR, \
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user