Skip to content

Don't assume particuliar order of AttachedFile segment - #24

Merged
peerless2012 merged 3 commits into
peerless2012:masterfrom
moi15moi:Avoid-possible-error
Oct 26, 2026
Merged

peerless2012 merged 3 commits into
peerless2012:masterfrom
moi15moi:Avoid-possible-error

Conversation

@moi15moi

Copy link
Copy Markdown
Contributor

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.

@peerless2012

Copy link
Copy Markdown
Owner

Does this fix #19 ?

@moi15moi

Copy link
Copy Markdown
Contributor Author

No, the problem with #19 is that you call ass_render_frame before ass_add_font.

@peerless2012

Copy link
Copy Markdown
Owner

No, the problem with #19 is that you call ass_render_frame before ass_add_font.

Due my test, that issue is because of MatroskaExtractor will stop parse when reach Cue tag.

Is there any mkv to test this pr?

@moi15moi

Copy link
Copy Markdown
Contributor Author

I don't know how I can edit the EBML of a mkv, so I don't know how I could create a mkv where the FileData is before FileName and FileMediaType.

I just know that the order isn't guaranteed, but I don't have any sample.

@moi15moi

Copy link
Copy Markdown
Contributor Author

Due my test, that issue is because of MatroskaExtractor will stop parse when reach Cue tag.

For me, when I use opengl (with of course a mkv where the attachments section is at the end of the file), it sometimes show me the font and sometime it doesn't. So, that's why I think it call ass_render_frame before ass_add_font.

@peerless2012

Copy link
Copy Markdown
Owner

I don't know how I can edit the EBML of a mkv, so I don't know how I could create a mkv where the FileData is before FileName and FileMediaType.

I just know that the order isn't guaranteed, but I don't have any sample.

Is there any docs or other player process like this?

@moi15moi

Copy link
Copy Markdown
Contributor Author

From https://www.matroska.org/technical/ordering.html

Except for the EBML Header and the CRC-32 Element, the EBML specification does not require any particular storage order for Elements.

@peerless2012

Copy link
Copy Markdown
Owner

We will kepp this pr and when we can find a mkv with this issue, then we can verify this pr and merge it.

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.
@moi15moi
moi15moi force-pushed the Avoid-possible-error branch from 720a11a to 5b69689 Compare October 24, 2026 15:49
@moi15moi

Copy link
Copy Markdown
Contributor Author

As a reminder, AttachedFile looks like this (from https://www.matroska.org/technical/diagram.html)

+------------------------------------------------+
| Attachments | AttachedFile | FileDescription   |
|             |              |-------------------|
|             |              | FileName          |
|             |              |-------------------|
|             |              | FileMediaType     |
|             |              |-------------------|
|             |              | FileData          |
|             |              |-------------------|
|             |              | FileUID           |
+------------------------------------------------+

mkvmerge always writes FileName and FileMimeType before FileData, but as said previously, the order isn't guarantee.

With this script (mkv_reorder_attachment.zip), I created a mkv where FileData is before FileName and FileMediaType: output_mkv.zip.

With the command mkvinfo --ui-language en_US output.mkv, you can see that the FileData is indeed before the FileName and the FileMediaType:

|+ Attachments
| + Attached
|  + File data: size 36812
|  + File name: Jester.ttf
|  + MIME type: font/ttf
|  + File UID: 15477550427935747237

Without this PR, I was getting this exception:

2026-10-24 11:18:02.035 31312-31337 LoadTask                io.github.peerless2012.ass           E  Unexpected exception loading stream
                                                                                                      java.lang.IllegalArgumentException: Required value was null.
                                                                                                          at io.github.peerless2012.ass.media.extractor.AssMatroskaExtractor.binaryElement(AssMatroskaExtractor.kt:85)
                                                                                                          at androidx.media3.extractor.mkv.MatroskaExtractor$InnerEbmlProcessor.binaryElement(MatroskaExtractor.java:2069)
                                                                                                          at androidx.media3.extractor.mkv.DefaultEbmlReader.read(DefaultEbmlReader.java:145)
                                                                                                          at androidx.media3.extractor.mkv.MatroskaExtractor.read(MatroskaExtractor.java:596)
                                                                                                          at androidx.media3.exoplayer.source.BundledExtractorsAdapter.read(BundledExtractorsAdapter.java:147)
                                                                                                          at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1146)
                                                                                                          at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:453)
                                                                                                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100)
                                                                                                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
                                                                                                          at java.lang.Thread.run(Thread.java:1572)
2026-10-24 11:18:02.039 31312-31336 ExoPlayerImplInternal   io.github.peerless2012.ass           E  Playback error
                                                                                                      androidx.media3.exoplayer.ExoPlaybackException: Source error
                                                                                                          at androidx.media3.exoplayer.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:927)
                                                                                                          at androidx.media3.exoplayer.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:903)
                                                                                                          at android.os.Handler.dispatchMessage(Handler.java:107)
                                                                                                          at android.os.Looper.loopOnce(Looper.java:242)
                                                                                                          at android.os.Looper.loop(Looper.java:362)
                                                                                                          at android.os.HandlerThread.run(HandlerThread.java:85)
                                                                                                      Caused by: androidx.media3.exoplayer.upstream.Loader$UnexpectedLoaderException: Unexpected IllegalArgumentException: Required value was null.
                                                                                                          at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:474)
                                                                                                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100)
                                                                                                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
                                                                                                          at java.lang.Thread.run(Thread.java:1572)
                                                                                                      Caused by: java.lang.IllegalArgumentException: Required value was null.
                                                                                                          at io.github.peerless2012.ass.media.extractor.AssMatroskaExtractor.binaryElement(AssMatroskaExtractor.kt:85)
                                                                                                          at androidx.media3.extractor.mkv.MatroskaExtractor$InnerEbmlProcessor.binaryElement(MatroskaExtractor.java:2069)
                                                                                                          at androidx.media3.extractor.mkv.DefaultEbmlReader.read(DefaultEbmlReader.java:145)
                                                                                                          at androidx.media3.extractor.mkv.MatroskaExtractor.read(MatroskaExtractor.java:596)
                                                                                                          at androidx.media3.exoplayer.source.BundledExtractorsAdapter.read(BundledExtractorsAdapter.java:147)
                                                                                                          at androidx.media3.exoplayer.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1146)
                                                                                                          at androidx.media3.exoplayer.upstream.Loader$LoadTask.run(Loader.java:453)
                                                                                                          at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1100) 
                                                                                                          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) 
                                                                                                          at java.lang.Thread.run(Thread.java:1572) 

With this PR, the mkv now play normally and we can see indeed the font.

@peerless2012
peerless2012 merged commit 6b60ad7 into peerless2012:master Oct 26, 2026
2 checks passed
@moi15moi
moi15moi deleted the Avoid-possible-error branch October 26, 2026 10:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants