[FFmpeg-devel] [PATCH 10/11] avformat/matroskaenc: write a CRC32 element on Tags
James Almer
jamrial at gmail.com
Tue Oct 4 02:37:06 EEST 2016
Implements part of ticket #4347
Signed-off-by: James Almer <jamrial at gmail.com>
---
This one got messy because we update Duration tags at the end of the muxing
process, and the entire master needs to be finalized before the CRC32 can be
calculated.
libavformat/matroskaenc.c | 58 +++++++++++++++++++++++++++++------------------
tests/ref/fate/rgb24-mkv | 4 ++--
tests/ref/lavf/mka | 4 ++--
tests/ref/lavf/mkv | 8 +++----
tests/ref/seek/lavf-mkv | 44 +++++++++++++++++------------------
5 files changed, 66 insertions(+), 52 deletions(-)
diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c
index c63ecdd..4dfcc55 100644
--- a/libavformat/matroskaenc.c
+++ b/libavformat/matroskaenc.c
@@ -107,6 +107,8 @@ typedef struct MatroskaMuxContext {
const AVClass *class;
int mode;
AVIOContext *dyn_bc;
+ AVIOContext *tags_bc;
+ ebml_master tags;
ebml_master segment;
int64_t segment_offset;
ebml_master cluster;
@@ -1343,6 +1345,7 @@ static int mkv_write_tag_targets(AVFormatContext *s,
unsigned int elementid, unsigned int uid,
ebml_master *tags, ebml_master* tag)
{
+ AVIOContext *pb;
MatroskaMuxContext *mkv = s->priv_data;
ebml_master targets;
int ret;
@@ -1351,14 +1354,15 @@ static int mkv_write_tag_targets(AVFormatContext *s,
ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_TAGS, avio_tell(s->pb));
if (ret < 0) return ret;
- *tags = start_ebml_master(s->pb, MATROSKA_ID_TAGS, 0);
+ start_ebml_master_crc32(s->pb, &mkv->tags_bc, tags, MATROSKA_ID_TAGS, 0);
}
+ pb = mkv->tags_bc;
- *tag = start_ebml_master(s->pb, MATROSKA_ID_TAG, 0);
- targets = start_ebml_master(s->pb, MATROSKA_ID_TAGTARGETS, 0);
+ *tag = start_ebml_master(pb, MATROSKA_ID_TAG, 0);
+ targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, 0);
if (elementid)
- put_ebml_uint(s->pb, elementid, uid);
- end_ebml_master(s->pb, targets);
+ put_ebml_uint(pb, elementid, uid);
+ end_ebml_master(pb, targets);
return 0;
}
@@ -1376,6 +1380,7 @@ static int mkv_check_tag_name(const char *name, unsigned int elementid)
static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int elementid,
unsigned int uid, ebml_master *tags)
{
+ MatroskaMuxContext *mkv = s->priv_data;
ebml_master tag;
int ret;
AVDictionaryEntry *t = NULL;
@@ -1386,13 +1391,13 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int eleme
while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) {
if (mkv_check_tag_name(t->key, elementid)) {
- ret = mkv_write_simpletag(s->pb, t);
+ ret = mkv_write_simpletag(mkv->tags_bc, t);
if (ret < 0)
return ret;
}
}
- end_ebml_master(s->pb, tag);
+ end_ebml_master(mkv->tags_bc, tag);
return 0;
}
@@ -1410,13 +1415,12 @@ static int mkv_check_tag(AVDictionary *m, unsigned int elementid)
static int mkv_write_tags(AVFormatContext *s)
{
MatroskaMuxContext *mkv = s->priv_data;
- ebml_master tags = {0};
int i, ret;
ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL);
if (mkv_check_tag(s->metadata, 0)) {
- ret = mkv_write_tag(s, s->metadata, 0, 0, &tags);
+ ret = mkv_write_tag(s, s->metadata, 0, 0, &mkv->tags);
if (ret < 0) return ret;
}
@@ -1426,26 +1430,28 @@ static int mkv_write_tags(AVFormatContext *s)
if (!mkv_check_tag(st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID))
continue;
- ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags);
+ ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &mkv->tags);
if (ret < 0) return ret;
}
if (s->pb->seekable && !mkv->is_live) {
for (i = 0; i < s->nb_streams; i++) {
+ AVIOContext *pb;
ebml_master tag_target;
ebml_master tag;
- mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags, &tag_target);
+ mkv_write_tag_targets(s, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &mkv->tags, &tag_target);
+ pb = mkv->tags_bc;
- tag = start_ebml_master(s->pb, MATROSKA_ID_SIMPLETAG, 0);
- put_ebml_string(s->pb, MATROSKA_ID_TAGNAME, "DURATION");
- mkv->stream_duration_offsets[i] = avio_tell(s->pb);
+ tag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, 0);
+ put_ebml_string(pb, MATROSKA_ID_TAGNAME, "DURATION");
+ mkv->stream_duration_offsets[i] = avio_tell(pb);
// Reserve space to write duration as a 20-byte string.
// 2 (ebml id) + 1 (data size) + 20 (data)
- put_ebml_void(s->pb, 23);
- end_ebml_master(s->pb, tag);
- end_ebml_master(s->pb, tag_target);
+ put_ebml_void(pb, 23);
+ end_ebml_master(pb, tag);
+ end_ebml_master(pb, tag_target);
}
}
@@ -1455,12 +1461,16 @@ static int mkv_write_tags(AVFormatContext *s)
if (!mkv_check_tag(ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID))
continue;
- ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id + mkv->chapter_id_offset, &tags);
+ ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id + mkv->chapter_id_offset, &mkv->tags);
if (ret < 0) return ret;
}
- if (tags.pos)
- end_ebml_master(s->pb, tags);
+ if (mkv->tags.pos) {
+ if (s->pb->seekable && !mkv->is_live)
+ put_ebml_void(s->pb, avio_tell(mkv->tags_bc) + ((mkv->mode != MODE_WEBM) ? 2 /* ebml id + data size */ + 4 /* CRC32 */ : 0));
+ else
+ end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, mkv->tags);
+ }
return 0;
}
@@ -2236,16 +2246,20 @@ static int mkv_write_trailer(AVFormatContext *s)
mkv->stream_durations[i]);
if (!mkv->is_live && mkv->stream_duration_offsets[i] > 0) {
- avio_seek(pb, mkv->stream_duration_offsets[i], SEEK_SET);
+ avio_seek(mkv->tags_bc, mkv->stream_duration_offsets[i], SEEK_SET);
snprintf(duration_string, 20, "%02d:%02d:%012.9f",
(int) duration_sec / 3600, ((int) duration_sec / 60) % 60,
fmod(duration_sec, 60));
- put_ebml_binary(pb, MATROSKA_ID_TAGSTRING, duration_string, 20);
+ put_ebml_binary(mkv->tags_bc, MATROSKA_ID_TAGSTRING, duration_string, 20);
}
}
}
+ if (mkv->tags.pos && !mkv->is_live) {
+ avio_seek(pb, mkv->tags.pos, SEEK_SET);
+ end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, mkv->tags);
+ }
avio_seek(pb, currentpos, SEEK_SET);
}
diff --git a/tests/ref/fate/rgb24-mkv b/tests/ref/fate/rgb24-mkv
index 01b069c..3cd1887 100644
--- a/tests/ref/fate/rgb24-mkv
+++ b/tests/ref/fate/rgb24-mkv
@@ -1,5 +1,5 @@
-f2ec884f82ecf5754afc0c9a2babe4aa *tests/data/fate/rgb24-mkv.matroska
-58352 tests/data/fate/rgb24-mkv.matroska
+cddd0f9c0efc6592bd3026b8c47471c3 *tests/data/fate/rgb24-mkv.matroska
+58358 tests/data/fate/rgb24-mkv.matroska
#tb 0: 1/10
#media_type 0: video
#codec_id 0: rawvideo
diff --git a/tests/ref/lavf/mka b/tests/ref/lavf/mka
index 1990715..cde5cf9 100644
--- a/tests/ref/lavf/mka
+++ b/tests/ref/lavf/mka
@@ -1,3 +1,3 @@
-927a5d1e7837735271f57b329f1c9d7a *./tests/data/lavf/lavf.mka
-43672 ./tests/data/lavf/lavf.mka
+afd0c76b5fd8ca5ee47d12af7f92d024 *./tests/data/lavf/lavf.mka
+43678 ./tests/data/lavf/lavf.mka
./tests/data/lavf/lavf.mka CRC=0x3a1da17e
diff --git a/tests/ref/lavf/mkv b/tests/ref/lavf/mkv
index 951feac..63ed7da 100644
--- a/tests/ref/lavf/mkv
+++ b/tests/ref/lavf/mkv
@@ -1,6 +1,6 @@
-b3599e3229821a84116b4f03f324a08b *./tests/data/lavf/lavf.mkv
-472938 ./tests/data/lavf/lavf.mkv
+aa0fabb3a1564adbdbd27310b1643ca3 *./tests/data/lavf/lavf.mkv
+472944 ./tests/data/lavf/lavf.mkv
./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
-c56b90945e6e14a9b4b7f1ab94e3ad28 *./tests/data/lavf/lavf.mkv
-320608 ./tests/data/lavf/lavf.mkv
+85f86c9d5641c2344b9b389f38fad890 *./tests/data/lavf/lavf.mkv
+320614 ./tests/data/lavf/lavf.mkv
./tests/data/lavf/lavf.mkv CRC=0xec6c3c68
diff --git a/tests/ref/seek/lavf-mkv b/tests/ref/seek/lavf-mkv
index 7bd1586..26df545 100644
--- a/tests/ref/seek/lavf-mkv
+++ b/tests/ref/seek/lavf-mkv
@@ -1,48 +1,48 @@
-ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 818 size: 208
+ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 824 size: 208
ret: 0 st:-1 flags:0 ts:-1.000000
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret: 0 st:-1 flags:1 ts: 1.894167
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret: 0 st: 0 flags:0 ts: 0.788000
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret: 0 st: 0 flags:1 ts:-0.317000
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret:-1 st: 1 flags:0 ts: 2.577000
ret: 0 st: 1 flags:1 ts: 1.471000
-ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320301 size: 209
+ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320307 size: 209
ret: 0 st:-1 flags:0 ts: 0.365002
-ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147007 size: 27925
+ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147013 size: 27925
ret: 0 st:-1 flags:1 ts:-0.740831
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret:-1 st: 0 flags:0 ts: 2.153000
ret: 0 st: 0 flags:1 ts: 1.048000
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret: 0 st: 1 flags:0 ts:-0.058000
-ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 818 size: 208
+ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 824 size: 208
ret: 0 st: 1 flags:1 ts: 2.836000
-ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320301 size: 209
+ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320307 size: 209
ret:-1 st:-1 flags:0 ts: 1.730004
ret: 0 st:-1 flags:1 ts: 0.624171
-ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147007 size: 27925
+ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147013 size: 27925
ret: 0 st: 0 flags:0 ts:-0.482000
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret: 0 st: 0 flags:1 ts: 2.413000
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret:-1 st: 1 flags:0 ts: 1.307000
ret: 0 st: 1 flags:1 ts: 0.201000
-ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 818 size: 208
+ret: 0 st: 1 flags:1 dts: 0.000000 pts: 0.000000 pos: 824 size: 208
ret: 0 st:-1 flags:0 ts:-0.904994
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret: 0 st:-1 flags:1 ts: 1.989173
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret: 0 st: 0 flags:0 ts: 0.883000
-ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292460 size: 27834
+ret: 0 st: 0 flags:1 dts: 0.971000 pts: 0.971000 pos: 292466 size: 27834
ret: 0 st: 0 flags:1 ts:-0.222000
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
ret:-1 st: 1 flags:0 ts: 2.672000
ret: 0 st: 1 flags:1 ts: 1.566000
-ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320301 size: 209
+ret: 0 st: 1 flags:1 dts: 0.993000 pts: 0.993000 pos: 320307 size: 209
ret: 0 st:-1 flags:0 ts: 0.460008
-ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147007 size: 27925
+ret: 0 st: 0 flags:1 dts: 0.491000 pts: 0.491000 pos: 147013 size: 27925
ret: 0 st:-1 flags:1 ts:-0.645825
-ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1034 size: 27837
+ret: 0 st: 0 flags:1 dts: 0.011000 pts: 0.011000 pos: 1040 size: 27837
--
2.9.1
More information about the ffmpeg-devel
mailing list