The mapping is taken from Picard's [1] and taglib's [2] documentation.

ID3:
    The `TSST` frame is part of ID3v2.4.0:
    > The 'Set subtitle' frame is intended for the subtitle of the part
    > of a set this track belongs to.

asf: WM/SetSubTitle
    The mapping in Microsoft's docs [3] maps `TSST` from ID3 to
`WM/SetSubTitle`.
    However, some taggers [4] [5] use `WM/SubTitle` instead.
    I believe this to be an error, especially since the official docs
    say otherwise.

MP4: ----:com.apple.iTunes:DISCSUBTITLE
    In my tests, iTunes did not respond to this attribute but it seems
    to be what all the sources that I have linked use.

RIFF: PRT1
    I have only found this in taglib's mapping [2]. The only other
    reference that I have found is on exiftool.org [6] where it is
    described as "part".

Vorbis: DISCSUBTITLE
    The official list [7] of standard field names is pretty short and
    does not include one for a disc/part subtitle. Some taggers use
    SETSUBTITLE here instead. However, I think DISCSUBTITLE is much more
    consistent with the already existing DISCNUMBER field and it matches
    what Picard and taglib do.

[1]: 
https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#disc-subtitle
[2]: https://taglib.org/api/p_propertymapping.html
[3]: https://learn.microsoft.com/en-gb/windows/win32/wmformat/id3-tag-support
[4]: 
https://github.com/quodlibet/quodlibet/blob/db95540de69c7f7cda662fbad6d90eeca89611ce/quodlibet/formats/wma.py#L43
[5]: 
https://invent.kde.org/multimedia/kid3/-/blob/989fb5b8f98e20387c704e229f8c8b9cd00ae453/src/plugins/taglibmetadata/taglibasfsupport.cpp#L93
[6]: https://exiftool.org/TagNames/RIFF.html
[7]: https://xiph.org/vorbis/doc/v-comment.html

Signed-off-by: Tau Gärtli <[email protected]>
---
 libavformat/asf.c           |  3 +++
 libavformat/avformat.h      |  1 +
 libavformat/id3v2.c         |  1 +
 libavformat/mov.c           |  8 +++++++-
 libavformat/movenc.c        | 40 +++++++++++++++++++++++++++++++++++++
 libavformat/riff.c          | 27 +++++++++++++------------
 libavformat/vorbiscomment.c | 10 ++++++----
 7 files changed, 72 insertions(+), 18 deletions(-)

diff --git a/libavformat/asf.c b/libavformat/asf.c
index 5c118d2dbe..5224a5d88d 100644
--- a/libavformat/asf.c
+++ b/libavformat/asf.c
@@ -37,6 +37,9 @@ const AVMetadataConv ff_asf_metadata_conv[] = {
     { "WM/Language",             "language"         },
     { "WM/OriginalFilename",     "filename"         },
     { "WM/PartOfSet",            "disc"             },
+    /* SetSubTitle can be found in this mapping:
+     * 
https://learn.microsoft.com/en-gb/windows/win32/wmformat/id3-tag-support */
+    { "WM/SetSubTitle",          "disc_subtitle"    },
     { "WM/Publisher",            "publisher"        },
     { "WM/Tool",                 "encoder"          },
     { "WM/TrackNumber",          "track"            },
diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index bd34132e00..a92f4796ba 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -386,6 +386,7 @@ struct AVFrame;
  creation_time-- date when the file was created, preferably in ISO 8601.
  date         -- date when the work was created, preferably in ISO 8601.
  disc         -- number of a subset, e.g. disc in a multi-disc collection.
+ disc_subtitle-- title of a subset, e.g. disc subtitle in a multi-disc 
collection.
  encoder      -- name/settings of the software/hardware that produced the file.
  encoded_by   -- person/group who created the file.
  filename     -- original name of the file.
diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 98969c67a0..729dc6bf96 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -70,6 +70,7 @@ const AVMetadataConv ff_id3v2_4_metadata_conv[] = {
     { "TSOA", "album-sort"    },
     { "TSOP", "artist-sort"   },
     { "TSOT", "title-sort"    },
+    { "TSST", "disc_subtitle" },
     { "TIT1", "grouping"      },
     { 0 }
 };
diff --git a/libavformat/mov.c b/libavformat/mov.c
index d19b213ffa..227fbf2b7b 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -5451,7 +5451,13 @@ static int mov_read_custom(MOVContext *c, AVIOContext 
*pb, MOVAtom atom)
                     sc->start_pad = priming;
             }
         }
-        if (strcmp(key, "cdec") != 0) {
+        if (strcmp(mean, "com.apple.iTunes") == 0 &&
+            strcmp(key, "DISCSUBTITLE") == 0) {
+            av_dict_set(&c->fc->metadata, "disc_subtitle", val,
+                        AV_DICT_DONT_STRDUP_VAL);
+            val = NULL;
+        }
+        else if (strcmp(key, "cdec") != 0) {
             av_dict_set(&c->fc->metadata, key, val,
                         AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
             key = val = NULL;
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index 802c37fc4a..e825d1fc03 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -4561,6 +4561,35 @@ static int mov_write_string_tag(AVIOContext *pb, const 
char *name,
     return size;
 }
 
+static int mov_write_freeform_tag(AVIOContext *pb, const char *mean,
+                                  const char *name, const char *data)
+{
+    if (!data || !data[0])
+        return 0;
+
+    static const char stub_flags[4] = {0, 0, 0, 0};
+
+    int64_t entry_pos = avio_tell(pb);
+    avio_wb32(pb, 0); /* size */
+    ffio_wfourcc(pb, "----"); /* freeform */
+
+    size_t mean_len = strlen(mean);
+    avio_wb32(pb, 12 + mean_len);
+    ffio_wfourcc(pb, "mean");
+    avio_write(pb, &stub_flags[0], sizeof(stub_flags));
+    avio_write(pb, mean, mean_len);
+
+    size_t name_len = strlen(name);
+    avio_wb32(pb, 12 + name_len);
+    ffio_wfourcc(pb, "name");
+    avio_write(pb, &stub_flags[0], sizeof(stub_flags));
+    avio_write(pb, name, name_len);
+
+    mov_write_string_data_tag(pb, data, 0, 1);
+
+    return update_size(pb, entry_pos);
+}
+
 static AVDictionaryEntry *get_metadata_lang(AVFormatContext *s,
                                             const char *tag, int *lang)
 {
@@ -4597,6 +4626,16 @@ static int mov_write_string_metadata(AVFormatContext *s, 
AVIOContext *pb,
     return mov_write_string_tag(pb, name, t->value, lang, long_style);
 }
 
+static int mov_write_custom_metadata(AVFormatContext *s, AVIOContext *pb,
+                                     const char *mean, const char *name,
+                                     const char *tag)
+{
+    AVDictionaryEntry *t = av_dict_get(s->metadata, tag, NULL, 0);
+    if (!t)
+        return 0;
+    return mov_write_freeform_tag(pb, mean, name, t->value);
+}
+
 /* iTunes bpm number */
 static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s)
 {
@@ -4785,6 +4824,7 @@ static int mov_write_ilst_tag(AVIOContext *pb, 
MOVMuxContext *mov,
     mov_write_trkn_tag(pb, mov, s, 0); // track number
     mov_write_trkn_tag(pb, mov, s, 1); // disc number
     mov_write_tmpo_tag(pb, s);
+    mov_write_custom_metadata(s, pb, "com.apple.iTunes", "DISCSUBTITLE", 
"disc_subtitle");
     return update_size(pb, pos);
 }
 
diff --git a/libavformat/riff.c b/libavformat/riff.c
index fc79d0ac21..cb99f95767 100644
--- a/libavformat/riff.c
+++ b/libavformat/riff.c
@@ -635,19 +635,20 @@ const AVCodecTag *const ff_wav_codec_tags_list[] = { 
ff_codec_wav_tags, NULL };
 #endif
 
 const AVMetadataConv ff_riff_info_conv[] = {
-    { "IART", "artist"     },
-    { "ICMT", "comment"    },
-    { "ICOP", "copyright"  },
-    { "ICRD", "date"       },
-    { "IGNR", "genre"      },
-    { "ILNG", "language"   },
-    { "INAM", "title"      },
-    { "IPRD", "album"      },
-    { "IPRT", "track"      },
-    { "ITRK", "track"      },
-    { "ISFT", "encoder"    },
-    { "ISMP", "timecode"   },
-    { "ITCH", "encoded_by" },
+    { "IART", "artist"        },
+    { "ICMT", "comment"       },
+    { "ICOP", "copyright"     },
+    { "ICRD", "date"          },
+    { "IGNR", "genre"         },
+    { "ILNG", "language"      },
+    { "INAM", "title"         },
+    { "IPRD", "album"         },
+    { "IPRT", "track"         },
+    { "ITRK", "track"         },
+    { "ISFT", "encoder"       },
+    { "ISMP", "timecode"      },
+    { "ITCH", "encoded_by"    },
+    { "PRT1", "disc_subtitle" },
     { 0 },
 };
 
diff --git a/libavformat/vorbiscomment.c b/libavformat/vorbiscomment.c
index e57cfa5e62..8a60d6802e 100644
--- a/libavformat/vorbiscomment.c
+++ b/libavformat/vorbiscomment.c
@@ -32,10 +32,12 @@
  * http://xiph.org/vorbis/doc/v-comment.html
  */
 const AVMetadataConv ff_vorbiscomment_metadata_conv[] = {
-    { "ALBUMARTIST", "album_artist"},
-    { "TRACKNUMBER", "track"  },
-    { "DISCNUMBER",  "disc"   },
-    { "DESCRIPTION", "comment" },
+    { "ALBUMARTIST",  "album_artist"  },
+    { "TRACKNUMBER",  "track"         },
+    { "DISCNUMBER",   "disc"          },
+    /* Adapted from 
<https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html#disc-subtitle>
 */
+    { "DISCSUBTITLE", "disc_subtitle" },
+    { "DESCRIPTION",  "comment"       },
     { 0 }
 };
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to