... | ... |
@@ -373,6 +373,27 @@ For example a 3D WebM clip can be created using the following command line: |
373 | 373 |
avconv -i sample_left_right_clip.mpg -an -c:v libvpx -metadata STEREO_MODE=left_right -y stereo_clip.webm |
374 | 374 |
@end example |
375 | 375 |
|
376 |
+This muxer supports the following options: |
|
377 |
+ |
|
378 |
+@table @option |
|
379 |
+ |
|
380 |
+@item reserve_index_space |
|
381 |
+By default, this muxer writes the index for seeking (called cues in Matroska |
|
382 |
+terms) at the end of the file, because it cannot know in advance how much space |
|
383 |
+to leave for the index at the beginning of the file. However for some use cases |
|
384 |
+-- e.g. streaming where seeking is possible but slow -- it is useful to put the |
|
385 |
+index at the beginning of the file. |
|
386 |
+ |
|
387 |
+If this option is set to a non-zero value, the muxer will reserve a given amount |
|
388 |
+of space in the file header and then try to write the cues there when the muxing |
|
389 |
+finishes. If the available space does not suffice, muxing will fail. A safe size |
|
390 |
+for most use cases should be about 50kB per hour of video. |
|
391 |
+ |
|
392 |
+Note that cues are only written if the output is seekable and this option will |
|
393 |
+have no effect if it is not. |
|
394 |
+ |
|
395 |
+@end table |
|
396 |
+ |
|
376 | 397 |
@section segment |
377 | 398 |
|
378 | 399 |
Basic stream segmenter. |
... | ... |
@@ -34,6 +34,7 @@ |
34 | 34 |
#include "libavutil/intreadwrite.h" |
35 | 35 |
#include "libavutil/lfg.h" |
36 | 36 |
#include "libavutil/mathematics.h" |
37 |
+#include "libavutil/opt.h" |
|
37 | 38 |
#include "libavutil/random_seed.h" |
38 | 39 |
#include "libavutil/samplefmt.h" |
39 | 40 |
|
... | ... |
@@ -79,6 +80,7 @@ typedef struct { |
79 | 79 |
#define MODE_WEBM 0x02 |
80 | 80 |
|
81 | 81 |
typedef struct MatroskaMuxContext { |
82 |
+ const AVClass *class; |
|
82 | 83 |
int mode; |
83 | 84 |
AVIOContext *dyn_bc; |
84 | 85 |
ebml_master segment; |
... | ... |
@@ -95,6 +97,9 @@ typedef struct MatroskaMuxContext { |
95 | 95 |
AVPacket cur_audio_pkt; |
96 | 96 |
|
97 | 97 |
int have_attachments; |
98 |
+ |
|
99 |
+ int reserve_cues_space; |
|
100 |
+ int64_t cues_pos; |
|
98 | 101 |
} MatroskaMuxContext; |
99 | 102 |
|
100 | 103 |
|
... | ... |
@@ -968,6 +973,11 @@ static int mkv_write_header(AVFormatContext *s) |
968 | 968 |
if (mkv->cues == NULL) |
969 | 969 |
return AVERROR(ENOMEM); |
970 | 970 |
|
971 |
+ if (pb->seekable && mkv->reserve_cues_space) { |
|
972 |
+ mkv->cues_pos = avio_tell(pb); |
|
973 |
+ put_ebml_void(pb, mkv->reserve_cues_space); |
|
974 |
+ } |
|
975 |
+ |
|
971 | 976 |
av_init_packet(&mkv->cur_audio_pkt); |
972 | 977 |
mkv->cur_audio_pkt.size = 0; |
973 | 978 |
|
... | ... |
@@ -1250,7 +1260,28 @@ static int mkv_write_trailer(AVFormatContext *s) |
1250 | 1250 |
|
1251 | 1251 |
if (pb->seekable) { |
1252 | 1252 |
if (mkv->cues->num_entries) { |
1253 |
- cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
|
1253 |
+ if (mkv->reserve_cues_space) { |
|
1254 |
+ int64_t cues_end; |
|
1255 |
+ |
|
1256 |
+ currentpos = avio_tell(pb); |
|
1257 |
+ avio_seek(pb, mkv->cues_pos, SEEK_SET); |
|
1258 |
+ |
|
1259 |
+ cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
|
1260 |
+ cues_end = avio_tell(pb); |
|
1261 |
+ if (cues_end > cuespos + mkv->reserve_cues_space) { |
|
1262 |
+ av_log(s, AV_LOG_ERROR, "Insufficient space reserved for cues: %d " |
|
1263 |
+ "(needed: %"PRId64").\n", mkv->reserve_cues_space, |
|
1264 |
+ cues_end - cuespos); |
|
1265 |
+ return AVERROR(EINVAL); |
|
1266 |
+ } |
|
1267 |
+ |
|
1268 |
+ if (cues_end < cuespos + mkv->reserve_cues_space) |
|
1269 |
+ put_ebml_void(pb, mkv->reserve_cues_space - (cues_end - cuespos)); |
|
1270 |
+ |
|
1271 |
+ avio_seek(pb, currentpos, SEEK_SET); |
|
1272 |
+ } else { |
|
1273 |
+ cuespos = mkv_write_cues(pb, mkv->cues, s->nb_streams); |
|
1274 |
+ } |
|
1254 | 1275 |
|
1255 | 1276 |
ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos); |
1256 | 1277 |
if (ret < 0) return ret; |
... | ... |
@@ -1291,7 +1322,22 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) |
1291 | 1291 |
return 0; |
1292 | 1292 |
} |
1293 | 1293 |
|
1294 |
+#define OFFSET(x) offsetof(MatroskaMuxContext, x) |
|
1295 |
+#define FLAGS AV_OPT_FLAG_ENCODING_PARAM |
|
1296 |
+static const AVOption options[] = { |
|
1297 |
+ { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning " |
|
1298 |
+ "of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, |
|
1299 |
+ { NULL }, |
|
1300 |
+}; |
|
1301 |
+ |
|
1294 | 1302 |
#if CONFIG_MATROSKA_MUXER |
1303 |
+static const AVClass matroska_class = { |
|
1304 |
+ .class_name = "matroska muxer", |
|
1305 |
+ .item_name = av_default_item_name, |
|
1306 |
+ .option = options, |
|
1307 |
+ .version = LIBAVUTIL_VERSION_INT, |
|
1308 |
+}; |
|
1309 |
+ |
|
1295 | 1310 |
AVOutputFormat ff_matroska_muxer = { |
1296 | 1311 |
.name = "matroska", |
1297 | 1312 |
.long_name = NULL_IF_CONFIG_SMALL("Matroska"), |
... | ... |
@@ -1312,10 +1358,18 @@ AVOutputFormat ff_matroska_muxer = { |
1312 | 1312 |
}, |
1313 | 1313 |
.subtitle_codec = AV_CODEC_ID_SSA, |
1314 | 1314 |
.query_codec = mkv_query_codec, |
1315 |
+ .priv_class = &matroska_class, |
|
1315 | 1316 |
}; |
1316 | 1317 |
#endif |
1317 | 1318 |
|
1318 | 1319 |
#if CONFIG_WEBM_MUXER |
1320 |
+static const AVClass webm_class = { |
|
1321 |
+ .class_name = "webm muxer", |
|
1322 |
+ .item_name = av_default_item_name, |
|
1323 |
+ .option = options, |
|
1324 |
+ .version = LIBAVUTIL_VERSION_INT, |
|
1325 |
+}; |
|
1326 |
+ |
|
1319 | 1327 |
AVOutputFormat ff_webm_muxer = { |
1320 | 1328 |
.name = "webm", |
1321 | 1329 |
.long_name = NULL_IF_CONFIG_SMALL("WebM"), |
... | ... |
@@ -1329,10 +1383,17 @@ AVOutputFormat ff_webm_muxer = { |
1329 | 1329 |
.write_trailer = mkv_write_trailer, |
1330 | 1330 |
.flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | |
1331 | 1331 |
AVFMT_TS_NONSTRICT, |
1332 |
+ .priv_class = &webm_class, |
|
1332 | 1333 |
}; |
1333 | 1334 |
#endif |
1334 | 1335 |
|
1335 | 1336 |
#if CONFIG_MATROSKA_AUDIO_MUXER |
1337 |
+static const AVClass mka_class = { |
|
1338 |
+ .class_name = "matroska audio muxer", |
|
1339 |
+ .item_name = av_default_item_name, |
|
1340 |
+ .option = options, |
|
1341 |
+ .version = LIBAVUTIL_VERSION_INT, |
|
1342 |
+}; |
|
1336 | 1343 |
AVOutputFormat ff_matroska_audio_muxer = { |
1337 | 1344 |
.name = "matroska", |
1338 | 1345 |
.long_name = NULL_IF_CONFIG_SMALL("Matroska"), |
... | ... |
@@ -1347,5 +1408,6 @@ AVOutputFormat ff_matroska_audio_muxer = { |
1347 | 1347 |
.write_trailer = mkv_write_trailer, |
1348 | 1348 |
.flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT, |
1349 | 1349 |
.codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, |
1350 |
+ .priv_class = &mka_class, |
|
1350 | 1351 |
}; |
1351 | 1352 |
#endif |
... | ... |
@@ -31,7 +31,7 @@ |
31 | 31 |
|
32 | 32 |
#define LIBAVFORMAT_VERSION_MAJOR 55 |
33 | 33 |
#define LIBAVFORMAT_VERSION_MINOR 0 |
34 |
-#define LIBAVFORMAT_VERSION_MICRO 0 |
|
34 |
+#define LIBAVFORMAT_VERSION_MICRO 1 |
|
35 | 35 |
|
36 | 36 |
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ |
37 | 37 |
LIBAVFORMAT_VERSION_MINOR, \ |