Recuperar video WebM generado por VirtualBox destrozado

Cuando me llamó el departamento indio de "Microsoft", dejé que se unieran a mi máquina virtual VirtualBox e inicié una captura de video para capturar cualquier detalle sobre ellos. Al hacerlo, VirtualBox crea archivos de video .webm.

Sin embargo, cuando ahora reproduzco ese archivo webm, veo que se destruyó justo donde cambié la resolución de la máquina virtual. La sesión duró una hora (uf...), y al final logré frustrar sus inútiles intentos de pirateo para establecer una contraseña del sistema en mi máquina y, en cambio, volví a iniciar sesión en la conexión que luego rompieron. Creo que luego vi un entorno de tablero de pantalla completa, ¿tal vez el de ellos? ¡Podría tener información muy útil si esto es cierto!

Parece que la manipulación es solo un problema de longitud de línea de escaneo en la transmisión de video. Lo complicado aquí es que el video en sí está correctamente en una resolución de 1024x768, pero la carga útil es solo un área de 800x600 en el medio (con bordes negros alrededor). Esa área interna es lo que se arruinó más en el video. Los bordes negros permanecen bien, por lo que es solo el flujo de datos de origen de VirtualBox para la parte central que se desalineó.

¿Alguien sabe de algún procedimiento o software que podría usar para tratar de desmantelar este video? Ya he visto que los archivos de video webm usan un estándar basado en Matroska y usan una codificación EBML; Ya intenté cambiar algunos valores de encabezados en la estructura EBML para alterar la resolución de la pantalla (haciendo que los bordes negros estén desalineados pero la carga media esté bien), pero eso no llevó a ninguna parte rápidamente (cada 5 segundos de video o algo así tiene su propio bloque de encabezado como bien).

Suma:

Para ser precisos: el video se renderizó a 1024x786 píxeles, mientras que la máquina virtual funcionó a 800x600. Esto da como resultado un borde negro grueso que rodea el contenido capturado interno durante todo el video. Una vez que aumenté el tamaño de la ventana de la máquina virtual (a, digamos, 1200x650, realmente no podría decir exactamente), el borde negro permaneció del mismo tamaño, solo el contenido interno se destruyó. Con destrozado quiero decir que parece que muestra las líneas de escaneo ahora más largas de 1200 píxeles y las envuelve en la longitud de la línea de escaneo de 800, por lo que cada siguiente línea de escaneo real se compensa con la diferencia de tamaño horizontal ya que la línea anterior está envuelta en ella. O al menos, eso es lo que pensé inicialmente, pero viéndolo de nuevo, también tengo mis dudas sobre esa teoría.

Bueno, eso no está nada claro :) He subido un cuadro aquí: fotograma de video de estafay un breve fragmento de video aquí: fragmento breve de video fraudulento (el problema ocurre a la mitad del fragmento)

Pero, para ser honesto, creo que será mejor que me rinda. Empiezo a sospechar que la única solución posible es capturar píxeles en los marcos antiguos y crear un nuevo video a partir de eso, si es que eso es una solución, es decir, demasiado esfuerzo. Sin embargo, es una pena, ya que realmente me gustaría revisar el contenido al final...

Solución:

Gracias a bukkojot, se me ocurrió la aplicación de seguimiento (destinada a Windows) que encaja en el medio de la línea de comandos ffmpeg que proporcionó; tal vez alguien puede encontrarlo útil? Tenga en cuenta que el "RGB24" en la línea de cmd debe ser "rgb24" cuando se usa la última versión de ffmpeg en Windows, que trae la línea de cmd que solía:

ffmpeg.exe -i scamvideo_problem.webm -f rawvideo -pix_fmt rgb24 pipe: | restorer.exe | ffmpeg -f rawvideo -pix_fmt rgb24 -s 1103x436 -i pipe: -vcodec libx264 resolvedvideo.avi

El video salió legible (aparte de los cambios de color), y todas las partes involucradas en él han sido notificadas (iTunes, gmail, TeamViewer y VICIdial).

De todos modos, este es el código C++ que terminé usando:

#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
using namespace std;

int main() {
    const size_t inLineSize = 1024 * 3;
    const size_t inFrameSize = 1024 * 768 * 3;
    const size_t outFrameSize = 1103 * 436 * 3;

    const size_t inPayloadLineSize = 800 * 3;
    const size_t inPayloadNumLines = 600;
    const size_t inPayloadFrameSize = inPayloadLineSize * inPayloadNumLines;
    const size_t inTopBorderNumLines = 84;
    const size_t inLeftBorderNumPixels = 112;
    const size_t inPayloadOffset = inLineSize * inTopBorderNumLines + inLeftBorderNumPixels * 3;

    const size_t outPadSize = outFrameSize - inPayloadFrameSize;

    _setmode(_fileno(stdin), _O_BINARY);
    _setmode(_fileno(stdout), _O_BINARY);

    char* inFrame = new char[inFrameSize];
    char* outPadding = new char[outPadSize];
    memset(outPadding, 0, outPadSize);
    while (!feof(stdin)) {
        size_t sizeLeft = inFrameSize;
        char* nextReadPos = inFrame;
        while (!feof(stdin) && sizeLeft > 0) {
            size_t bytesRead = fread(nextReadPos, 1, sizeLeft, stdin);
            sizeLeft -= bytesRead;
            nextReadPos += bytesRead;
            if (sizeLeft > 0) {
                Sleep(100);
            }
        }
        if (!feof(stdin)) {
            char* inPayloadPos = inFrame;
            inPayloadPos += inPayloadOffset;
            for (size_t inLineNr = 0; inLineNr < inPayloadNumLines; ++inLineNr, inPayloadPos += inLineSize) {
                fwrite(inPayloadPos, 1, inPayloadLineSize, stdout);
            }
            fwrite(outPadding, 1, outPadSize, stdout);
        }
    }
    return 0;
}
Por destrozado, ¿solo te refieres al tamaño o errores de decodificación?
@Mulvya: es... Actualizaré la publicación para dar más detalles :)

Respuestas (1)

Después de un poco de manipulación... Ya ves...

ingrese la descripción de la imagen aquí

La forma más fácil para usted:

  1. Escriba una aplicación muy simple en C, que leerá 1024*768*3 bytes y rellenará con ceros hasta 1327*768*3 bytes. Es fácil para ti.

  2. Volcar píxeles sin procesar con ffmpeg, canalizar datos a su aplicación, canalizar datos a ffmpeg de vuelta

Algo como:

ffmpeg -i scamvideo.avi -f rawvideo -pix_fmt RGB24 - | ./a.out | ffmpeg -f rawvideo -pix_fmt RGB24 -s 1327x768 -i - -vcodec libx264 newvideo.avi

Todas las demás opciones a tu gusto. Creo que tienes una idea.

La luminancia se ha alineado, pero no la crominancia, que tendrá la mitad del tamaño.
@bukkojot: ¡MUCHAS GRACIAS! ¡No sabes lo mucho que quería restaurar ese video! Ahora, para la ejecución :) De hecho, podré hacerlo, pero primero tengo que encontrar algo de tiempo... tengo el video de todos modos, así que no irá a ninguna parte mientras tanto.
@Mulvya: * el croma: si es lo suficientemente legible, soy un campista feliz :)
Empecé a trabajar en él de todos modos, pero supongo que mi tiempo no es el factor limitante, es el tiempo de ejecución :)
Esta tarea muy fácil. Necesitas una hora o dos.
También lo pensé, pero como estoy trabajando en Windows resultó más difícil de lo previsto. La conversión funciona, pero no puedo hacer que ffmpeg se conecte correctamente a mi aplicación. Saltarse las tuberías y escribir a través de archivos temporales tampoco es viable para la salida RAW a esa velocidad de fotogramas durante 1 hora :) Continuará después de este fin de semana.
Asegúrese de usar el modo binario. Debajo de las ventanas es muy importante. Usar winapi para lectura/escritura binaria
@bukkojot: el modo binario fue clave. Y... ¡Recuperé el video! Bueno, solo los 3/4 superiores de los marcos, ya que esa es la única parte que quedó abarrotada en la parte interna de 800x600. De todos modos, obtuve la dirección de correo electrónico que intentaron usar para recibir tarjetas de regalo de iTunes, así como el escritorio que tienen frente a ellos (usan VICIdial Web Client). ¡Éxito! Voy a contactar a fraude@itunes, fraude@teamviewer, fraude@VICIdial y tal vez a la policía local (pero creo que no me molestaré con el último). ¡No podría haberlo hecho sin su respuesta!
Y otro comentario para cualquiera que intente la misma hazaña: NO use Powershell; en él puede usar canalizaciones, pero tiene la desagradable costumbre de intentar almacenar en búfer toda la salida estándar de una aplicación antes de canalizarla a la siguiente... ganó No funciona en este caso, por supuesto. Me tomó un poco de tirón de pelo para darme cuenta de eso...