describeAudio lacks the unparseable arm describeVideo has, and its fallback would print a NUL #74

Closed
opened 2026-08-24 21:28:27 +00:00 by JMR-dev · 1 comment
JMR-dev commented 2026-08-24 21:28:27 +00:00 (Migrated from github.com)

Found while writing the #58 tests. Latent, not live — but one assignment away, and the failure mode is a control character in the UI.

describeAudio is missing the arm describeVideo has

app/src/main/java/org/libremediaconverter/model/CodecNames.kt:

fun describeVideo(name: String?): String = when {
    name == null -> "Unknown"
    name == InputProbe.UNPARSEABLE -> "Unrecognised"     // <-- this arm
    else -> videoFromName(name)?.label ?: name
}

fun describeAudio(name: String?): String = when {
    name == null -> "Unknown"
                                                         // <-- no equivalent
    else -> audioFromName(name)?.label ?: name
}

The lookup below them does handle the sentinel on both sides — audioFromName opens with
null, InputProbe.UNPARSEABLE -> null. So the pair disagrees about whether the sentinel is a
special case: the lookup says yes, describeAudio says no and falls through to ?: name.

Why the failure mode is worse than a wrong label

InputProbe.UNPARSEABLE is declared as "\u0000unparseable" — it opens with a NUL. The fallback
returns that string verbatim, so the source-info card would render a Text whose content begins
with U+0000. Not a mislabel; a control character in the UI.

It is not reachable today, and that is the argument for fixing it cheaply

Only one site assigns the sentinel — MediaProbe.kt:46 — and it sets videoCodec and
kind = InputKind.UNPARSEABLE together. FileCard's UNPARSEABLE branch renders its own
explanatory line and never calls describeAudio. Nothing assigns audioCodec = UNPARSEABLE.

Same shape as D9 in docs/defect-audit.md: correct today by accident of what the callers happen to
do, wrong the moment a probe path sets an audio codec it could not identify.

Fix

Add the arm, so the two read the same:

    name == InputProbe.UNPARSEABLE -> "Unrecognised"

Unit-testable, and it needs a test either way — CodecNamesTest already exists and covers the
MIME to FFprobe to enum round trip.

Mutation: delete the arm again and the new test must go red on the string "Unrecognised".
Note the existing describeVideo arm has no test of its own either — pin both while you are in
there, or the symmetric bug can come back on the other side.

Note for whoever writes it

#58's brief asserted both functions had this arm; they do not. That claim came from a reading of the
file rather than from the file. Check the source, not the ticket.

_Found while writing the #58 tests. Latent, not live — but one assignment away, and the failure mode is a control character in the UI._ ### `describeAudio` is missing the arm `describeVideo` has `app/src/main/java/org/libremediaconverter/model/CodecNames.kt`: ```kotlin fun describeVideo(name: String?): String = when { name == null -> "Unknown" name == InputProbe.UNPARSEABLE -> "Unrecognised" // <-- this arm else -> videoFromName(name)?.label ?: name } fun describeAudio(name: String?): String = when { name == null -> "Unknown" // <-- no equivalent else -> audioFromName(name)?.label ?: name } ``` The lookup below them **does** handle the sentinel on both sides — `audioFromName` opens with `null, InputProbe.UNPARSEABLE -> null`. So the pair disagrees about whether the sentinel is a special case: the lookup says yes, `describeAudio` says no and falls through to `?: name`. ### Why the failure mode is worse than a wrong label `InputProbe.UNPARSEABLE` is declared as `"\u0000unparseable"` — it **opens with a NUL**. The fallback returns that string verbatim, so the source-info card would render a `Text` whose content begins with U+0000. Not a mislabel; a control character in the UI. ### It is not reachable today, and that is the argument for fixing it cheaply Only one site assigns the sentinel — `MediaProbe.kt:46` — and it sets `videoCodec` and `kind = InputKind.UNPARSEABLE` together. `FileCard`'s `UNPARSEABLE` branch renders its own explanatory line and never calls `describeAudio`. **Nothing assigns `audioCodec = UNPARSEABLE`.** Same shape as D9 in `docs/defect-audit.md`: correct today by accident of what the callers happen to do, wrong the moment a probe path sets an audio codec it could not identify. ### Fix Add the arm, so the two read the same: ```kotlin name == InputProbe.UNPARSEABLE -> "Unrecognised" ``` **Unit-testable, and it needs a test either way** — `CodecNamesTest` already exists and covers the MIME to FFprobe to enum round trip. **Mutation:** delete the arm again and the new test must go red on the string `"Unrecognised"`. Note the existing `describeVideo` arm has **no test of its own** either — pin both while you are in there, or the symmetric bug can come back on the other side. ### Note for whoever writes it #58's brief asserted both functions had this arm; they do not. That claim came from a reading of the file rather than from the file. Check the source, not the ticket.
JMR-dev commented 2026-08-25 03:22:26 +00:00 (Migrated from github.com)

Same family as #87, filed today: two functions over one codec vocabulary that stopped matching.

This ticket is describeAudio missing describeVideo's unparseable arm. #87 is CodecNames.videoFromName and AndroidDeviceCodecs.mimeForCodecName disagreeing about five names (x264, hev1, x265, vp09, mpeg4).

The vocabulary is written out in at least four places — CodecNames, AndroidDeviceCodecs, Media3Engine.videoMimeTypeFor/audioMimeTypeFor, and MediaProbe.shortName — and none of the four has a test. Worth fixing together: one cross-check test that fails when any two disagree would cover this ticket and #87, and would catch the next divergence, which per-function arm tests will not.

Same family as **#87**, filed today: two functions over one codec vocabulary that stopped matching. This ticket is `describeAudio` missing `describeVideo`'s unparseable arm. #87 is `CodecNames.videoFromName` and `AndroidDeviceCodecs.mimeForCodecName` disagreeing about five names (`x264`, `hev1`, `x265`, `vp09`, `mpeg4`). **The vocabulary is written out in at least four places** — `CodecNames`, `AndroidDeviceCodecs`, `Media3Engine.videoMimeTypeFor`/`audioMimeTypeFor`, and `MediaProbe.shortName` — and **none of the four has a test**. Worth fixing together: one cross-check test that fails when any two disagree would cover this ticket and #87, and would catch the next divergence, which per-function arm tests will not.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMediaConverter#74