From 5b69689bd1a829ec308d785f25e0de20bbba4cb3 Mon Sep 17 00:00:00 2001 From: moi15moi Date: Sat, 24 Oct 2026 11:19:15 -0400 Subject: [PATCH 1/3] Don't assume particuliar order of AttachedFile segment The previous code was assuming that, in the AttachedFile, the name and mime type were always before the data. This isn't true because the order is not guaranteed by the Matroska specification. --- .../media/extractor/AssMatroskaExtractor.kt | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt index b195292..3283f85 100644 --- a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt +++ b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt @@ -21,6 +21,7 @@ open class AssMatroskaExtractor( private var currentAttachmentName: String? = null private var currentAttachmentMime: String? = null + private var currentAttachmentData: ByteArray? = null internal val subtitleSample = subtitleSampleField.get(this) as ParsableByteArray @@ -66,7 +67,16 @@ open class AssMatroskaExtractor( assHandler.setVideoSize(track.width, track.height) super.endMasterElement(id) } - ID_ATTACHED_FILE -> clearAttachment() + ID_ATTACHED_FILE -> { + val attachmentName = requireNotNull(currentAttachmentName) + val attachmentMime = requireNotNull(currentAttachmentMime) + val attachmentData = requireNotNull(currentAttachmentData) + + if (attachmentMime in fontMimeTypes) { + assHandler.addFont(attachmentName, attachmentData) + } + clearAttachment() + } else -> super.endMasterElement(id) } } @@ -82,16 +92,8 @@ open class AssMatroskaExtractor( override fun binaryElement(id: Int, contentSize: Int, input: ExtractorInput) { when (id) { ID_FILE_DATA -> { - val attachmentName = requireNotNull(currentAttachmentName) - val attachmentMime = requireNotNull(currentAttachmentMime) - - if (attachmentMime in fontMimeTypes) { - val data = ByteArray(contentSize) - input.readFully(data, 0, contentSize) - assHandler.addFont(attachmentName, data) - } else { - input.skipFully(contentSize) - } + currentAttachmentData = ByteArray(contentSize) + input.readFully(currentAttachmentData!!, 0, contentSize) } else -> super.binaryElement(id, contentSize, input) } @@ -100,6 +102,7 @@ open class AssMatroskaExtractor( private fun clearAttachment() { currentAttachmentName = null currentAttachmentMime = null + currentAttachmentData = null } companion object { From 0eb87e1526ba6ce4893dc358dbef8c5837b547af Mon Sep 17 00:00:00 2001 From: moi15moi Date: Sat, 24 Oct 2026 11:57:12 -0400 Subject: [PATCH 2/3] Support font attachment with the "application/octet-stream" --- .../ass/media/extractor/AssMatroskaExtractor.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt index 3283f85..b143c45 100644 --- a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt +++ b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt @@ -72,7 +72,11 @@ open class AssMatroskaExtractor( val attachmentMime = requireNotNull(currentAttachmentMime) val attachmentData = requireNotNull(currentAttachmentData) - if (attachmentMime in fontMimeTypes) { + // Detect fonts like the spec says: https://github.com/ietf-wg-cellar/matroska-specification/blob/1a943ead9bb4c67b02b966cebafe51c8c074e703/cellar-matroska/attachments.md?plain=1#L87-L111 + val isFont = attachmentMime in fontMimeTypes || + (attachmentMime == "application/octet-stream" && + fontExtensions.any { attachmentName.lowercase().endsWith(it) }) + if (isFont) { assHandler.addFont(attachmentName, attachmentData) } clearAttachment() @@ -127,6 +131,8 @@ open class AssMatroskaExtractor( "application/x-font-ttf", ) + val fontExtensions = listOf(".ttf", ".otf", ".ttc", ".otc") + val extractorOutput = MatroskaExtractor::class.java.getDeclaredField("extractorOutput").apply { isAccessible = true } From b87b91e97f5daac9ed61a4a937fe18194de3da20 Mon Sep 17 00:00:00 2001 From: moi15moi Date: Sat, 24 Oct 2026 12:03:06 -0400 Subject: [PATCH 3/3] Detect more font mime type Those are from mpv: https://github.com/mpv-player/mpv/blob/a39482e7a580e64ea58ac0e1fc2838100b6320d3/sub/sd_ass.c#L144-L154 --- .../peerless2012/ass/media/extractor/AssMatroskaExtractor.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt index b143c45..525615f 100644 --- a/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt +++ b/lib_ass_media/src/main/java/io/github/peerless2012/ass/media/extractor/AssMatroskaExtractor.kt @@ -119,6 +119,7 @@ open class AssMatroskaExtractor( const val ID_FILE_DATA = 0x465C val fontMimeTypes = listOf( + "font/collection", "font/ttf", "font/otf", "font/sfnt", @@ -128,7 +129,9 @@ open class AssMatroskaExtractor( "application/font-woff", "application/x-truetype-font", "application/vnd.ms-opentype", + "application/x-font", "application/x-font-ttf", + "application/x-font-otf", ) val fontExtensions = listOf(".ttf", ".otf", ".ttc", ".otc")