Commit 45314ff2 authored by Andreas Rheinhardt's avatar Andreas Rheinhardt

avformat/matroskaenc: Use random TrackUID

Up until now, the TrackUID of a Matroska track which is supposed to be
random was not random at all: It always coincided with the TrackNumber
which is usually the 1-based index of the corresponding stream in the
array of AVStreams. This has been changed: It is now set via an AVLFG
if AVFMT_FLAG_BITEXACT is not set. Otherwise it is set like it is set
now (the only change happens if an explicit track number has been
chosen via dash_track_number, because the system used in the normal
situation is now used, too). In particular, no FATE tests need to be
updated.

This also fixes a bug in case the dash_track_number option was used:
In this case the TrackUID was set to the provided number, but the tags
were written with a TagTrackUID simply based upon the index, so that
the tags didn't apply to the track they ought to apply to.
Signed-off-by: 's avatarAndreas Rheinhardt <andreas.rheinhardt@gmail.com>
parent bd7dea3f
...@@ -93,6 +93,7 @@ typedef struct mkv_cues { ...@@ -93,6 +93,7 @@ typedef struct mkv_cues {
typedef struct mkv_track { typedef struct mkv_track {
int write_dts; int write_dts;
int has_cue; int has_cue;
uint64_t uid;
int sample_rate; int sample_rate;
int64_t sample_rate_offset; int64_t sample_rate_offset;
int64_t last_timestamp; int64_t last_timestamp;
...@@ -1115,8 +1116,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, ...@@ -1115,8 +1116,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv,
track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0); track = start_ebml_master(pb, MATROSKA_ID_TRACKENTRY, 0);
put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER, put_ebml_uint (pb, MATROSKA_ID_TRACKNUMBER,
mkv->is_dash ? mkv->dash_track_number : i + 1); mkv->is_dash ? mkv->dash_track_number : i + 1);
put_ebml_uint (pb, MATROSKA_ID_TRACKUID, put_ebml_uint (pb, MATROSKA_ID_TRACKUID, mkv->tracks[i].uid);
mkv->is_dash ? mkv->dash_track_number : i + 1);
put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet) put_ebml_uint (pb, MATROSKA_ID_TRACKFLAGLACING , 0); // no lacing (yet)
if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) if ((tag = av_dict_get(st->metadata, "title", NULL, 0)))
...@@ -1569,6 +1569,7 @@ static int mkv_write_tags(AVFormatContext *s) ...@@ -1569,6 +1569,7 @@ static int mkv_write_tags(AVFormatContext *s)
tagp = (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live ? &tag : NULL; tagp = (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live ? &tag : NULL;
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
AVStream *st = s->streams[i]; AVStream *st = s->streams[i];
mkv_track *track = &mkv->tracks[i];
if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT) if (st->codecpar->codec_type == AVMEDIA_TYPE_ATTACHMENT)
continue; continue;
...@@ -1577,7 +1578,7 @@ static int mkv_write_tags(AVFormatContext *s) ...@@ -1577,7 +1578,7 @@ static int mkv_write_tags(AVFormatContext *s)
continue; continue;
ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID,
i + 1, tagp); track->uid, tagp);
if (ret < 0) return ret; if (ret < 0) return ret;
if (tagp) { if (tagp) {
...@@ -1783,10 +1784,6 @@ static int mkv_write_header(AVFormatContext *s) ...@@ -1783,10 +1784,6 @@ static int mkv_write_header(AVFormatContext *s)
version = 4; version = 4;
} }
mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
if (!mkv->tracks) {
return AVERROR(ENOMEM);
}
ebml_header = start_ebml_master(pb, EBML_ID_HEADER, MAX_EBML_HEADER_SIZE); ebml_header = start_ebml_master(pb, EBML_ID_HEADER, MAX_EBML_HEADER_SIZE);
put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLVERSION , 1);
put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1); put_ebml_uint (pb, EBML_ID_EBMLREADVERSION , 1);
...@@ -2607,8 +2604,28 @@ static int webm_query_codec(enum AVCodecID codec_id, int std_compliance) ...@@ -2607,8 +2604,28 @@ static int webm_query_codec(enum AVCodecID codec_id, int std_compliance)
return 0; return 0;
} }
static uint64_t mkv_get_uid(const mkv_track *tracks, int i, AVLFG *c)
{
while (1) {
uint64_t uid;
int k;
uid = (uint64_t)av_lfg_get(c) << 32;
uid |= av_lfg_get(c);
if (!uid)
continue;
for (k = 0; k < i; k++) {
if (tracks[k].uid == uid)
break;
}
if (k == i)
return uid;
}
}
static int mkv_init(struct AVFormatContext *s) static int mkv_init(struct AVFormatContext *s)
{ {
MatroskaMuxContext *mkv = s->priv_data;
AVLFG c;
int i; int i;
if (s->nb_streams > MAX_TRACKS) { if (s->nb_streams > MAX_TRACKS) {
...@@ -2637,7 +2654,23 @@ static int mkv_init(struct AVFormatContext *s) ...@@ -2637,7 +2654,23 @@ static int mkv_init(struct AVFormatContext *s)
s->internal->avoid_negative_ts_use_pts = 1; s->internal->avoid_negative_ts_use_pts = 1;
} }
mkv->tracks = av_mallocz_array(s->nb_streams, sizeof(*mkv->tracks));
if (!mkv->tracks) {
return AVERROR(ENOMEM);
}
if (!(s->flags & AVFMT_FLAG_BITEXACT))
av_lfg_init(&c, av_get_random_seed());
for (i = 0; i < s->nb_streams; i++) { for (i = 0; i < s->nb_streams; i++) {
mkv_track *track = &mkv->tracks[i];
if (s->flags & AVFMT_FLAG_BITEXACT) {
track->uid = i + 1;
} else {
track->uid = mkv_get_uid(mkv->tracks, i, &c);
}
// ms precision is the de-facto standard timescale for mkv files // ms precision is the de-facto standard timescale for mkv files
avpriv_set_pts_info(s->streams[i], 64, 1, 1000); avpriv_set_pts_info(s->streams[i], 64, 1, 1000);
} }
......
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