¿Cómo dura este archivo .mp4 de 596523 horas?

Encontré este archivo mp4 de broma en línea. (Advertencia: enlace de descarga directa a un archivo de 8 mb). Tanto los reproductores multimedia como ffmpeg enumeran el archivo con una longitud de 596523:14:07.00 (!). Lo primero que supuse fue que el video podría haber usado una velocidad de fotogramas muy baja, pero ffmpeg enumera una velocidad de fotogramas de 10 fps, sin fotogramas que tengan una velocidad de fotogramas variable. ¿Qué está pasando en la codificación de este archivo para darle una longitud tan larga?

Aquí hay una pista: si alguien te dice "Tengo 100 m de altura", ¿ realmente necesita medir 100 m para decir esto?

Respuestas (1)

Hay varias cosas que podemos señalar aquí:

  1. El archivo deja de reproducirse después de las 0:05:30.
  2. Si remuxea el archivo (mkvtools, por ejemplo), se muestra 5:30 como la duración.
  3. El archivo original, de hecho, muestra la longitud ridícula.

Entonces, aunque es una broma divertida, no es tan genial como pensé al principio. Nadie ha descubierto cómo hacer un bucle infinito de cuadros o algo similar. Esto parece ser solo un encabezado del archivo que no coincide con los datos.

¿Cómo calcula el reproductor (o la mayoría de las herramientas) la duración del video? No leen todo el archivo, de lo contrario los tiempos de carga de los archivos no serían prácticos. Entonces, al comienzo del archivo hay un marcador que dice la longitud, y el jugador simplemente confía en él.

Repasemos las matemáticas:

596523:14:07.00 = ((596523*60)+14)*60+7 = 2147483647 seconds
2147483647 (base 10) = 7FFFFFFF (base 16)

Oh, ese es un buen número. Ahora abramos el archivo con un editor hexadecimal, justo al principio vemos

 00000000:  00 00 00 18 66 74 79 70  6d 70 34 32 00 00 00 00  ....ftypmp42....
 00000010:  6d 70 34 32 6d 70 34 31  00 01 69 7b 6d 6f 6f 76  mp42mp41..i{moov
 00000020:  00 00 00 6c 6d 76 68 64  00 00 00 00 dd 69 a6 fb  ...lmvhd.....i..
 00000030:  dd 69 a6 fb 00 00 00 01  7f ff ff ff 00 01 00 00  .i..............

Ahí está nuestro culpable, justo en la marca 0x38. Vamos a editarlo y ver qué pasa. De hecho, obtengo una "broma" más divertida si cambio 7f a ff al principio. Para comprender por qué funciona, consulte ¿Cómo se almacenan los números negativos en la memoria? .

Tengo curiosidad, ¿cuál es el chiste "más divertido"?
@ Tvde1 se eliminaron los comentarios que lo insinuaban, pero obtienes una longitud negativa
Me hace preguntarme por qué el campo de longitud está definido (si realmente lo está) como firmado, ya que las longitudes negativas nunca tienen sentido. Pero probablemente para una portabilidad/compatibilidad más simple con otro software.
@Ray ¿Qué fue una muy buena discusión que fue eliminada por un moderador, con respecto a por qué es un int firmado en lugar de no firmado? No voy a volver a escribirlo todo, solo para que se elimine, lo siento.
@v010dya Es extraño por qué no se movió al chat. Gracias por hacérmelo saber.
@Ray Los enteros con y sin signo tienen la misma representación de bits para los números positivos. La mayoría del software utilizará la firma porque es más rápido en lenguajes como C++ gracias a un comportamiento indefinido. Por ejemplo, el compilador puede usar de forma segura operaciones de 64 bits en estos bits de 32 bits sin verificar el ajuste. También puede usar analizadores estáticos y ubsan para detectar el desbordamiento, lo que no puede hacer para entradas sin firmar, ya que nunca se desbordan. (También gracias SE mods por eliminar información útil)