History

avformat/matroskaenc: Check chapter ids for duplicates

Up until now, there has been no check that each chapter has a unique id; there was only a check for whether a chapter id is zero (this happens often when the chapters originated from a format that lacks the concept of chapter id and simply counts from zero) which is invalid in Matroska. In this case the chapter ids are offset by 1 to make them nonnegative. Yet offsetting won't fix duplicate ids, therefore this is changed to simply create new chapter uids when the input chapter uids don't conform to the requirements of Matroska (in which case it can be presumed that they did not originate from Matroska, so that we don't need to bother to preserve them).

Andreas Rheinhardt committed 5 years ago

Commit e1e6a5c1 parent 57853951 file · +19 −13Browse files

Unified · Split

libavformat/matroskaenc.c+19−13
@@ -1625,24 +1625,29 @@ static int mkv_write_tags(AVFormatContext *s) · 1624 unmodified lines
16251625 return 0;
16261626 }
16271627
1628+static int mkv_new_chapter_ids_needed(const AVFormatContext *s)
1629+{
1630+ for (unsigned i = 0; i < s->nb_chapters; i++) {
1631+ if (!s->chapters[i]->id)
1632+ return 1;
1633+ for (unsigned j = 0; j < i; j++)
1634+ if (s->chapters[j]->id == s->chapters[i]->id)
1635+ return 1;
1636+ }
1637+ return 0;
1638+}
1639+
16281640 static int mkv_write_chapters(AVFormatContext *s)
16291641 {
16301642 MatroskaMuxContext *mkv = s->priv_data;
16311643 AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb;
16321644 ebml_master editionentry;
1633− uint64_t chapter_id_offset = 0;
16341645 AVRational scale = {1, 1E9};
1635− int i, ret;
1646+ int ret, create_new_ids;
16361647
16371648 if (!s->nb_chapters || mkv->wrote_chapters)
16381649 return 0;
16391650
1640− for (i = 0; i < s->nb_chapters; i++)
1641− if (!s->chapters[i]->id) {
1642− chapter_id_offset = 1;
1643− break;
1644− }
1645−
16461651 ret = start_ebml_master_crc32(&dyn_cp, mkv);
16471652 if (ret < 0)
16481653 return ret;
@@ -1656,12 +1661,15 @@ static int mkv_write_chapters(AVFormatContext *s) · 7 unmodified lines
16561661 } else
16571662 tags = NULL;
16581663
1659− for (i = 0; i < s->nb_chapters; i++) {
1664+ create_new_ids = mkv_new_chapter_ids_needed(s);
1665+
1666+ for (unsigned i = 0; i < s->nb_chapters; i++) {
16601667 ebml_master chapteratom, chapterdisplay;
16611668 const AVChapter *c = s->chapters[i];
16621669 int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale);
16631670 int64_t chapterend = av_rescale_q(c->end, c->time_base, scale);
16641671 const AVDictionaryEntry *t;
1672+ uint64_t uid = create_new_ids ? i + 1ULL : (uint32_t)c->id;
16651673 if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) {
16661674 av_log(s, AV_LOG_ERROR,
16671675 "Invalid chapter start (%"PRId64") or end (%"PRId64").\n",
@@ -1671,8 +1679,7 @@ static int mkv_write_chapters(AVFormatContext *s) · 3 unmodified lines
16711679 }
16721680
16731681 chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0);
1674− put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID,
1675− (uint32_t)c->id + chapter_id_offset);
1682+ put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid);
16761683 put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart);
16771684 put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend);
16781685 if ((t = av_dict_get(c->metadata, "title", NULL, 0))) {
@@ -1685,8 +1692,7 @@ static int mkv_write_chapters(AVFormatContext *s) · 6 unmodified lines
16851692
16861693 if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) {
16871694 ret = mkv_write_tag(mkv, c->metadata, tags, NULL,
1688− MATROSKA_ID_TAGTARGETS_CHAPTERUID,
1689− (uint32_t)c->id + chapter_id_offset);
1695+ MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid);
16901696 if (ret < 0)
16911697 goto fail;
16921698 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t