FragmentedMp4Extractor: mfra-indexed fMP4 with zero moov duration is seekable but reports C.TIME_UNSET duration
Los mantenedores suelen responder en 5 días
@snow2405 ya está trabajando en esto.
Desde el 7/11/2026.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Version
Media3 1.11.1
More version details
Also present on main: the new getTrackDurationUs falls back to the mdhd duration, which is 0 in these files as well.
Devices that reproduce the issue
Pixel 9a, Android 17
Devices that do not reproduce the issue
None known. The behaviour comes from the extractor, not from the device.
Reproducible in the demo app?
Not tested
Reproduction steps
This follows up #3088. Since 1.11, DefaultExtractorsFactory always sets FLAG_READ_MFRA_FOR_SEEK_MAP, so a fragmented MP4 indexed only by a trailing mfra is now seekable. When the moov carries no duration, though, it still has no duration.
ffmpeg writes exactly this layout with -movflags frag_keyframe+empty_moov: mvhd/tkhd/mdhd durations are all 0, there is no mehd and no sidx, and the only index is the mfra at the end:
ftyp, moov (durations 0, mvex with trex only), moof, mdat, moof, mdat, ..., mfra
- Make a 3 s file:
ffmpeg -f lavfi -i color=c=black:s=32x32:r=10:d=3 -f lavfi -i sine=f=440:d=3:sample_rate=8000 -c:v libx264 -g 10 -pix_fmt yuv420p -c:a aac -b:a 16k -shortest -movflags frag_keyframe+empty_moov out.mp4(ffprobe reportsduration=3.2). - Play it with
ProgressiveMediaSourceand the default extractors, or run it throughFragmentedMp4Extractorand look at theSeekMapit outputs.
Instrumented test (Pixel 9a). It sniffs with DefaultExtractorsFactory, drives read(), reopens the input at the offset on RESULT_SEEK, and stops at the first seekMap():
FragmentedMp4Extractor -> FragmentedMp4Extractor$MfraSeekMap
isSeekable = true
durationUs = -9223372036854775807 (C.TIME_UNSET)
getSeekPoints(Long.MAX_VALUE) = [timeUs=2200000, position=7099]
Expected result
The duration is known once the mfra has been read, matching what ffprobe/ffmpeg report (3.2 s here, 292.4 s for the real file below). The player shows the duration and the seek bar can be used from the start.
Actual result
MfraSeekMap is seekable, but its duration is C.TIME_UNSET, because it takes durationUs from the moov. ProgressiveMediaPeriod.onLoadCompleted fills in a duration only after the whole file has loaded. For a 27 MB, 4:52 video with a capped buffer that happens near the end of playback, so until then the UI shows no duration or remaining time and the seek bar has nothing to map onto, even though seeking would work.
The tfra entries only give fragment start times, so they alone would undercount. In the real file the last tfra time is 287.84 s against 292.4 s, and fragments there vary from 0.12 s to 7 s. ffmpeg gets the exact value by also parsing the last fragment: its tfdt plus the trun sample durations (falling back to tfhd/trex defaults).
Possible fix: when the moov duration is unset and the mfra was parsed, read the moof the last tfra entry points to (the extractor is already positioned at the end of the file for mfro/mfra), compute tfdt + sum(sample durations) for the primary track, and pass that as the MfraSeekMap duration. If that read fails, the last tfra time is still a better lower bound than TIME_UNSET.
Media
A real-world file (fragmented MP4, 27,652,257 bytes, 292.4 s, H.264 + AAC, 110 fragments): https://blossom.primal.net/b3553ff5ac31930d6962de5fd16db55594e71dc2abfec8e14447d9205e3e3953.mp4
The 3 s synthetic file from step 1 shows the same behaviour.
Bug Report
- You will email the zip file produced by
adb bugreportto [email protected] after filing this issue.
- Lenguaje dominante
- Java
- Estrellas
- 3.1k
- Forks
- 1k
- Merge medio
- 7 d 12 h
- PR fusionados (30 d)
- 5
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de androidx/media
-
CompositionPlayer.release() leaks its playback thread and FrameProcessor when no composition was setPosiblemente ocupada @droid-girl la tomó hace 4 días. Abiertoediting preview
Dificultad 2/5 Medio día Aptitud para principiantes 62/100
androidx/media#3506 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 5 días
-
bug needs triage
Dificultad 4/5 3-5 días Aptitud para principiantes 38/100
Los mantenedores suelen responder en 5 días
-
playback iphone11 video very laggy in MTK chipsetsPosiblemente ocupada @microkatz la tomó hace 2 días. Abiertobug needs triage
androidx/media#3520 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 5 días
-
MultipleInputVideoGraph leaks the sync object passed to onInputFrameProcessed (file descriptor exhaustion on Adreno)Posiblemente ocupada @claincly la tomó hace 2 días. Abiertoediting
androidx/media#3519 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 5 días
-
Media3 reports H.264 [email protected] as supported by a [email protected] hardware decoderPosiblemente ocupada @microkatz la tomó hace 2 días. Abiertobug needs triage
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
androidx/media#3518 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 5 días
Todos los issues de androidx/media
Issues similares
-
Bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 60/100
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 68/100
Vakore/ZappierGames#285 ·
-
[S26b-4] Runbook and usage still describe deb suite as a pass-through runner whose skips do not failAbiertopriority: low Review effort [1-5]: 4 status: needs-triage type: bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
carlos-emr/carlos#6074 ·
Los mantenedores suelen responder en 1 día
-
On Windows, a relative command with `/` is looked up in the PATH instead of the working directoryAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 77/100
redhat-developer/lsp4ij#1896 ·
Los mantenedores suelen responder en 1 día